antd vue中,如何在form表单中的自定义组件使用v-decorator
作者:散装java
antd vue中在form表单中的自定义组件使用v-decorator
问题描述
项目需要,在表单中上传图片,所以要自己定以一个上传图片的组件,直接在form中使用,但是普通的自定义组件无法使用表单的v-decorator。
分析
转自官方的一段话
this.form.getFieldDecorator(id, options) 和 v-decorator="[id, options]"
经过 getFieldDecorator或v-decorator 包装的控件,表单控件会自动添加 value(或 valuePropName 指定的其他属性) onChange(或 trigger 指定的其他属性),数据同步将被 Form 接管,这会导致以下结果:
- 你不再需要也不应该用 onChange 来做同步,但还是可以继续监听 onChange 等事件。
- 你不能用控件的 value defaultValue 等属性来设置表单域的值,默认值可以用 getFieldDecorator 或 v-decorator 里的 initialValue。
- 你不应该用 v-model,可以使用 this.form.setFieldsValue 来动态改变表单值。
大概描述一下就是,一旦在form下使用了v-decorator之后,就不需要使用v-model,其实实现上也有所相同,在自定义组件中需要自己定以model的东西,详细可以查阅官网。
简单说明
通俗来说,想使用v-decorator,就必须要有个value想子组件传递数据。
和一个change方法将子组件的数据变动告诉父组件,下面看部分代码
model: { prop: 'value', event: 'change' }, props: { value: { type: String // 这个参数是v-decorator给子组件传值用的 // 这里不要给默认值, 在form下使用会爆警告 Warning: SquareUpload `default value` can not collect, please use `option.initialValue` to set default value. } } watch: { // 监听数据变化,及时提交给父组件 fileList: { deep: true, immediate: true, handler: function (newV, oldV) { // 向父组件更新 this.$emit('change', temp) } } }
注意:value不要给默认值,不然会爆警告default value can not collect, please use option.initialValue to set default value.
例子,封装一个上传图片的组件,在form中使用
子组件
<template> <div class="clearfix"> <a-upload :showRemoveIcon="false" :action="url" list-type="picture-card" :file-list="fileList" @preview="handlePreview" @change="handleChange" > <div v-if="fileList.length < max && isShow"> <a-icon type="plus" /> <div class="ant-upload-text"> Upload </div> </div> </a-upload> <a-modal :visible="previewVisible" :footer="null" @cancel="handleCancel"> <img alt="example" style="width: 100%" :src="previewImage" /> </a-modal> </div> </template> <script> import config from '@/views/constant/constantConfig' function getBase64 (file) { return new Promise((resolve, reject) => { const reader = new FileReader() reader.readAsDataURL(file) reader.onload = () => resolve(reader.result) reader.onerror = error => reject(error) }) } export default { name: 'SquareUpload', model: { prop: 'value', event: 'change' }, props: { value: { type: String // 这个参数是v-decorator给子组件传值用的 // 这里不要给默认值, 在form下使用会爆警告 Warning: SquareUpload `default value` can not collect, please use `option.initialValue` to set default value. }, // 上传地址 url: { type: String, default: config.uploadUrl }, isShow: { type: Boolean, default: true }, // 最多上传数量 max: { type: Number, default: 8 } }, data () { return { previewVisible: false, previewImage: '', fileList: [] } }, methods: { handleCancel () { this.previewVisible = false }, // 处理预览 async handlePreview (file) { if (!file.url && !file.preview) { file.preview = await getBase64(file.originFileObj) } this.previewImage = file.url || file.preview this.previewVisible = true }, handleChange ({ file, fileList }) { this.fileList = fileList } }, watch: { // 监听数据变化,及时提交给父组件 fileList: { deep: true, immediate: true, handler: function (newV, oldV) { if (this.fileList.length === 0) { return } this.fileList = newV const temp = this.fileList.filter(item => item.status !== 'uploading').map(item => (item.uid < 0 && item.name) || item.response.data.newFileName).join(',') // 向父组件更新 this.$emit('change', temp) } }, // 监听父组件传递过来的图片列表信息 value: { deep: true, immediate: true, handler: function (newV) { // 数据为空的三种情况 if (newV === null || newV === '' || newV === undefined) { this.fileList = [] return } let count = -1 let temp = [] const tempList = [] temp = newV.split(',') temp.forEach(item => { tempList.push({ uid: count, name: item, status: 'done', url: config.baseImgUrl + item }) count-- }) this.fileList = tempList } } } } </script> <style> /* you can make up upload button and sample style by using stylesheets */ .ant-upload-select-picture-card i { font-size: 32px; color: #999; } .ant-upload-select-picture-card .ant-upload-text { margin-top: 8px; color: #666; } </style>
父组件使用
<a-form-item label="上传标题图片" :labelCol="labelCol" :wrapperCol="wrapperCol"> <SquareUpload :isShow="!showable" v-decorator="['serveTitleImg', {rules: [{required: true, message: '请选择图片'}]}]"></SquareUpload> </a-form-item>
v-decorator antd vue的理解
v-decorator是ant Design的控件验证属性
经过 getFieldDecorator 或 v-decroator 包装的控件,表单控件会自动添加 value onChange 或者 trigger ,数据同步由Form接管,这会导致以下结果
- 你不在需要也不应该用 onChange 同步,但是可以继续监听 onChange事件
- 你不能用控件的 value defaultValue等属性来设置表单域的值,默认值可以用 getFieldDecorator 或 v-decorator里的 initialValue
- 你不应该用 v-model 可以使用 this.form.setFieldsValue 来动态改变表单值
定义form:
<template> <div class="main"> <a-form id="formLogin" class="user-layout-login" ref="formLogin" :form="form" @submit="handleSubmit" > <a-form-item> <a-input size="large" type="text" placeholder="账户: " v-decorator="[ 'username', {initialValue:'',rules: [{ required: true, message: '请输入帐户名或邮箱地址' }, { validator: handleUsernameOrEmail }], validateTrigger: 'change'} ]" > <a-icon slot="prefix" type="user" :style="{ color: 'rgba(0,0,0,.25)' }" /> </a-input> </a-form-item> </a-form> </div> </template> <script> ... export default { ... data () { return { ... form: this.$form.createForm(this), } }, created () { }, ... } </script>
v-decroator取值
this.form.vaidateFields((err, values) => { console.log(values) // {username: ''} })
v-decroator赋值
this.form.setFieldsValue({ username: '设置值' })
清空表单数据
this.form.resetFields()
总结
以上为个人经验,希望能给大家一个参考,也希望大家多多支持脚本之家。