看板
This commit is contained in:
@@ -0,0 +1,29 @@
|
||||
import type { ExtractPropTypes, PropType } from 'vue';
|
||||
import type { FormRules, InputAlign, FormErrorType, InputLabelPosition } from '../../types/global';
|
||||
import { baseProps } from '../common/props';
|
||||
|
||||
/**
|
||||
* u-form 组件 Props 类型定义
|
||||
* @description 表单组件属性
|
||||
*/
|
||||
export const FormProps = {
|
||||
...baseProps,
|
||||
/** 当前form的需要验证字段的集合 */
|
||||
model: { type: Object as PropType<Record<string, any>>, default: () => ({}) },
|
||||
/** 表单验证规则 */
|
||||
rules: { type: Object as PropType<FormRules>, default: () => ({}) },
|
||||
/** 有错误时的提示方式,message-提示信息,border-如果input设置了边框,变成呈红色,border-bottom-下边框呈现红色,none-无提示 */
|
||||
errorType: { type: Array as PropType<FormErrorType[]>, default: () => ['message', 'toast'] },
|
||||
/** 是否显示表单域的下划线边框 */
|
||||
borderBottom: { type: Boolean, default: true },
|
||||
/** label的位置,left-左边,top-上边 */
|
||||
labelPosition: { type: String as PropType<InputLabelPosition>, default: 'left' },
|
||||
/** label的宽度,单位rpx */
|
||||
labelWidth: { type: [String, Number] as PropType<string | number>, default: 90 },
|
||||
/** label字体的对齐方式 */
|
||||
labelAlign: { type: String as PropType<InputAlign>, default: 'left' },
|
||||
/** label的样式,对象形式 */
|
||||
labelStyle: { type: Object as PropType<Record<string, any>>, default: () => ({}) }
|
||||
};
|
||||
|
||||
export type FormProps = ExtractPropTypes<typeof FormProps>;
|
||||
@@ -0,0 +1,135 @@
|
||||
<template>
|
||||
<view class="u-form" :class="customClass" :style="$u.toStyle(customStyle)">
|
||||
<slot />
|
||||
</view>
|
||||
</template>
|
||||
|
||||
<script lang="ts">
|
||||
export default {
|
||||
name: 'u-form',
|
||||
options: {
|
||||
addGlobalClass: true,
|
||||
// #ifndef MP-TOUTIAO
|
||||
virtualHost: true,
|
||||
// #endif
|
||||
styleIsolation: 'shared'
|
||||
}
|
||||
};
|
||||
</script>
|
||||
|
||||
<script setup lang="ts">
|
||||
import { FormProps } from './types';
|
||||
import { computed, ref } from 'vue';
|
||||
import { $u, useParent } from '../..';
|
||||
|
||||
/**
|
||||
* form 表单
|
||||
* @description 此组件一般用于表单场景,可以配置Input输入框,Select弹出框,进行表单验证等。
|
||||
* @tutorial https://uviewpro.cn/zh/components/form.html
|
||||
* @property {Object} model 表单数据对象
|
||||
* @property {Boolean} border-bottom 是否显示表单域的下划线边框
|
||||
* @property {String} label-position 表单域提示文字的位置,left-左侧,top-上方
|
||||
* @property {String Number} label-width 提示文字的宽度,单位rpx(默认90)
|
||||
* @property {Object} label-style label的样式,对象形式
|
||||
* @property {String} label-align label的对齐方式
|
||||
* @property {Object} rules 通过ref设置,见官网说明
|
||||
* @property {Array} error-type 错误的提示方式,数组形式,见上方说明(默认['message'])
|
||||
* @example <u-form :model="form" ref="uForm"></u-form>
|
||||
*/
|
||||
|
||||
const props = defineProps(FormProps);
|
||||
|
||||
useParent('u-form');
|
||||
|
||||
interface ErrorItem {
|
||||
prop: string;
|
||||
message: string;
|
||||
}
|
||||
|
||||
// 存储当前form下的所有u-form-item的实例
|
||||
const fields = ref<any[]>([]);
|
||||
|
||||
// 校验规则
|
||||
const rules = ref<Record<string, any>>(props.rules);
|
||||
|
||||
/**
|
||||
* 设置校验规则
|
||||
* @param newRules 校验规则对象
|
||||
*/
|
||||
function setRules(newRules: Record<string, any>) {
|
||||
rules.value = newRules;
|
||||
}
|
||||
|
||||
/**
|
||||
* 清空所有u-form-item组件的内容,本质上是调用了u-form-item组件中的resetField()方法
|
||||
*/
|
||||
function resetFields() {
|
||||
fields.value.forEach((field: any) => {
|
||||
field.resetField && field.resetField();
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* 校验全部数据
|
||||
* @param callback 校验回调
|
||||
* @returns Promise<boolean>
|
||||
*/
|
||||
function validate(callback?: (valid: boolean, errorArr: ErrorItem[]) => void): Promise<boolean> {
|
||||
return new Promise(resolve => {
|
||||
// 对所有的u-form-item进行校验
|
||||
let valid = true; // 默认通过
|
||||
let count = 0; // 用于标记是否检查完毕
|
||||
let errorArr: ErrorItem[] = []; // 存放错误信息
|
||||
if (fields.value.length === 0) {
|
||||
resolve(true);
|
||||
if (typeof callback === 'function') callback(true, []);
|
||||
return;
|
||||
}
|
||||
// 调用每一个u-form-item实例的validation的校验方法
|
||||
fields.value.forEach((field: any) => {
|
||||
// 如果任意一个u-form-item校验不通过,就意味着整个表单不通过
|
||||
field.validation &&
|
||||
field.validation('', (error: any) => {
|
||||
if (error) {
|
||||
valid = false;
|
||||
errorArr.push({ prop: field.prop, message: error });
|
||||
}
|
||||
// 当历遍了所有的u-form-item时,调用promise的then方法
|
||||
if (++count === fields.value.length) {
|
||||
resolve(valid); // 进入promise的then方法
|
||||
// 判断是否设置了toast的提示方式,只提示最前面的表单域的第一个错误信息
|
||||
if (
|
||||
props.errorType.indexOf('none') === -1 &&
|
||||
props.errorType.indexOf('toast') >= 0 &&
|
||||
errorArr.length > 0
|
||||
) {
|
||||
errorArr[0].message && $u.toast(errorArr[0].message);
|
||||
}
|
||||
// 调用回调方法
|
||||
if (typeof callback === 'function') callback(valid, errorArr);
|
||||
}
|
||||
});
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
defineExpose({
|
||||
setRules,
|
||||
resetFields,
|
||||
validate,
|
||||
addField(field: any) {
|
||||
if (!fields.value.includes(field)) fields.value.push(field);
|
||||
},
|
||||
removeField(field: any) {
|
||||
fields.value = fields.value.filter(f => f.prop !== field.prop);
|
||||
},
|
||||
fields,
|
||||
rules,
|
||||
props,
|
||||
model: computed(() => props.model)
|
||||
});
|
||||
</script>
|
||||
|
||||
<style scoped lang="scss">
|
||||
@import '../../libs/css/style.components.scss';
|
||||
</style>
|
||||
Reference in New Issue
Block a user