| | |
| | | /** |
| | | * CFormItem |
| | | * CFormItem - 表单套装组件,单项包囊器 |
| | | * @author Tevin |
| | | * @tutorial rules see https://github.com/yiminghe/async-validator#type |
| | | */ |
| | | |
| | | <template> |
| | | <view class="c-form-item"> |
| | | <view class="c-form-item-label"> |
| | | <text |
| | | class="required" |
| | | v-if="required" |
| | | >*</text> |
| | | <text>{{label || name}}</text> |
| | | </view> |
| | | <slot |
| | | :value="formData[name]" |
| | | :onChange="evt=>onChange(evt)" |
| | | /> |
| | | <slot :itemRes="itemRes" /> |
| | | </view> |
| | | </template> |
| | | |
| | |
| | | export default { |
| | | name: 'CFormItem', |
| | | props: { |
| | | // 表单数据资源(表单组件内部机制专用) |
| | | formRes: Object, |
| | | // 表单项字段键名 |
| | | name: String, |
| | | // 表单项中文名 |
| | | label: String, |
| | | // 表单项验证规则之是否必填 |
| | | required: Boolean, |
| | | // 表单项验证规则之复合规则 |
| | | // 例如:[{type:'string', min: 2, max: 100}] |
| | | // 常用项: |
| | | // type string 类型,常见有 string、number、boolean、array、object、url、email |
| | | // len number string 类型时为字符串长度;number 类型时为确定数字; array 类型时为数组长度 |
| | | // max number 必须设置 type:string 类型为字符串最大长度;number 类型时为最大值;array 类型时为数组最大长度 |
| | | // min number 必须设置 type:string 类型为字符串最小长度;number 类型时为最小值;array 类型时为数组最小长度 |
| | | // pattern RegExp 正则表达式匹配 |
| | | // required boolean 是否为必选字段 |
| | | // transform (value) => any 将字段值转换成目标值后进行校验 |
| | | // message string 错误信息,不设置时会通过模板自动生成 |
| | | rules: Array, |
| | | formData: Object, |
| | | // 表单是否禁用 |
| | | disabled: Boolean, |
| | | }, |
| | | data() { |
| | | return {}; |
| | | return { |
| | | error: false, |
| | | }; |
| | | }, |
| | | computed: { |
| | | itemRes() { |
| | | return { |
| | | formData: this.formRes.formData, |
| | | name: this.name, |
| | | label: this.label, |
| | | required: this.isRequired, |
| | | disabled: this.disabled, |
| | | error: this.error, |
| | | onChange: evt => this.onChange(evt), |
| | | }; |
| | | }, |
| | | isRequired() { |
| | | if (this.required) { |
| | | return true; |
| | | } else { |
| | | if (!this.rules || this.rules.length === 0) { |
| | | return false; |
| | | } else if (this.rules.length > 0) { |
| | | for (let rule of this.rules) { |
| | | if (rule.required) { |
| | | return true; |
| | | } |
| | | } |
| | | return false; |
| | | } |
| | | } |
| | | }, |
| | | }, |
| | | methods: { |
| | | onChange(evt) { |
| | |
| | | !hasOwn.call(evt, 'constructor') && |
| | | !hasOwn.call(evt.constructor.prototype, 'isPrototypeOf') |
| | | ) { |
| | | throw new Error('错误的表单项 onChange 参数类型!(At: ' + this.name + ')'); |
| | | return; |
| | | throw new Error( |
| | | '错误的表单项 onChange 参数类型!(At: ' + this.name + ')' |
| | | ); |
| | | } |
| | | } |
| | | // 未改变值不触发 |
| | | if (this.formData[this.name] === evt) { |
| | | if (this.formRes.formData[this.name] === evt) { |
| | | return; |
| | | } |
| | | this.formData.$handleChange({ |
| | | this.formRes.$handleChange({ |
| | | [this.name]: evt, |
| | | }); |
| | | }, |
| | |
| | | this.$nextTick(() => { |
| | | // 未设置验证 |
| | | if (!this.required && !this.rules) { |
| | | this.formData.$regItemValidator(this.name, () => { |
| | | this.formRes.$regItemValidator(this.name, validateType => { |
| | | this.error = false; |
| | | return Promise.resolve({ |
| | | name: this.name, |
| | | passed: true, |
| | | }); |
| | | }); |
| | | } else { |
| | | // 验证规则 |
| | | const descriptor = this.rules || []; |
| | | if (this.required) { |
| | | descriptor.unshift({ |
| | |
| | | const validator = new Schema({ |
| | | [this.name]: descriptor, |
| | | }); |
| | | validator.messages(validateMsgs); // 自定义验证消息 |
| | | this.formData.$regItemValidator(this.name, () => { |
| | | // 汉化通用验证消息 |
| | | validator.messages(validateMsgs); |
| | | // 注册验证 |
| | | let errTimer = null; |
| | | this.formRes.$regItemValidator(this.name, validateType => { |
| | | return validator |
| | | .validate({ |
| | | [this.name]: this.formData[this.name], |
| | | [this.name]: this.formRes.formData[this.name], |
| | | }) |
| | | .then( |
| | | (res) => { |
| | | res => { |
| | | this.error = false; |
| | | return { |
| | | name: this.name, |
| | | passed: true, |
| | | }; |
| | | }, |
| | | ({ errors, fields }) => { |
| | | if (validateType !== 'msgOnly') { |
| | | this.error = true; |
| | | clearTimeout(errTimer); |
| | | errTimer = setTimeout(() => { |
| | | this.error = false; |
| | | }, 5000); |
| | | } |
| | | return { |
| | | name: this.name, |
| | | passed: false, |
| | |
| | | }); |
| | | }, |
| | | beforeDestroy() { |
| | | this.formData.$regItemValidator(this.name, null); |
| | | this.formRes.$regItemValidator(this.name, null); |
| | | }, |
| | | }; |
| | | </script> |