CNCEC_APP/uni_modules/uview-pro/components/u-form/u-form.vue

136 lines
4.3 KiB
Vue
Raw Normal View History

2026-03-25 14:54:15 +08:00
<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>