在 Vue 中多表单深层次嵌套结构,创建响应式属性,以及多层级表单验证
在 Vue 中多表单深层次嵌套结构,创建响应式属性,以及多层级表单验证文章目录在 Vue 中多表单深层次嵌套结构,创建响应式属性,以及多层级表单验证设置响应式属性表单验证设置响应式属性在 Vue 中,只有在跟级别中创建的属性,才具有响应式,如果后期手动添加,如使用 this.xxx = xxx这种方式创建的属性是不具有响应式的。在 Vue里面,封装了 7 个方法,使用如下的方法来添加属性,同样可以
在 Vue 中多表单深层次嵌套结构,创建响应式属性,以及多层级表单验证
设置响应式属性
在 Vue 中,只有在跟级别中创建的属性,才具有响应式,如果后期手动添加,如使用 this.xxx = xxx
这种方式创建的属性是不具有响应式的。
在 Vue里面,封装了 7 个方法,使用如下的方法来添加属性,同样可以创建响应式属性,并触发视图更新:
push()
pop()
shift()
unshift()
splice()
sort()
reverse()
如果不使用以上的方法,Vue 也提供了$set
方法来设置响应式属性,使用方式为this.$set(obj, newObj, value)
,在 Vue 的单文件组件里,大概是这样写的:
<script>
export default {
data() {
return {
obj: {}
}
},
methods: {
setValue() {
this.$set(this.obj, 'name', 'tim')
}
}
}
</script>
以上的代码表示,在 obj
里面,添加一个名为 name
值为 value
的属性。添加完之后,data 里面应该是这样的:
data() {
return {
obj: {
name: 'tim'
}
}
}
为了验证一下有效性,我们新建一个组件,ui 框架选用 element,来测试一下到底是否可行:
<template>
<div class="test">
<el-form ref="form" :model="form" label-width="80px">
<el-form-item label="name">
<el-input v-model="form.name"></el-input>
</el-form-item>
</el-form>
<el-button type="primary" @click="testFun">test</el-button>
</div>
</template>
<script>
export default {
name: 'test',
data() {
return {
form: {
}
}
},
methods: {
testFun() {
this.form.name = 'tim'
}
}
}
</script>
<style scoped></style>
先点击 test
按钮,我们往 form 里面添加了 name 属性,然后在表单输入值,发现输入不进去,打开 devtools
发现值也没有改变。
我们把 testFun
函数改写一下:
testFun() {
this.$set(this.form, 'name' 'tim')
}
这回在测试一下,先点击 test
按钮,然后发现表单被赋上值了,然后修改表单同样能够更新值。
以上表示,如果我们没有一开始在 data 里面创建跟级别的属性,需要使用 $set
来创建。
不过我们要说的不止是这个,而是创建多层嵌套的二维三维数组和对象的响应式,并触发视图更新。实际应用主要在表单的多层嵌套上,需要复原数据的情况下。
现在假设我们需要复原的数据为如下格式:
let copyData = [
[
{
name: 'tim',
age: 10
},
{
name: 'tim',
age: 20
}
],
[
{
name: 'andy',
age: 15
},
{
name: 'andy',
age: 30
},
]
]
这里面,既有数组又有对象,基本能把创建多维数据的响应式属性讲清楚。对于创建响应式数组和对象的原理,可以点击这里查看官网的介绍(建议看一眼之后,再来看这个例子),在此只提供实例进行讲解。
- 首先,我们先创建一个初始化页面,一般来说,我们不可能创建一个空的表单 data,所以需要填入属性,只不过没有值而已。
<template>
<div class="test">
<el-form ref="form" :model="form" label-width="80px">
<div class="parent" v-for="(parent, index) in form.list" :key="`parent-${index}`">
<div class="child" v-for="(child, idx) in parent" :key="`child-${idx}`">
<el-form-item label="name">
<el-input v-model="child.name"></el-input>
</el-form-item>
<el-form-item label="age">
<el-input v-model="child.age"></el-input>
</el-form-item>
</div>
</div>
</el-form>
<el-button type="primary" @click="testFun">test</el-button>
</div>
</template>
<script>
export default {
name: "test",
data() {
return {
form: {
list: [
[
{
name: "",
age: ""
}
]
]
}
};
},
};
</script>
<style scoped></style>
以上是完整的一个单 Vue 文件。主要是初始化了一个嵌套的多层级表单。
如上,我们在表单里修改内容,在 devtools 里面,可以看到值能够更新
2. 有了以上的布局结构,我们就可以模拟数据了。
let copyData = {
list: [
[
{
name: "tim",
age: 10
},
{
name: "tim",
age: 20
}
],
[
{
name: "andy",
age: 15
},
{
name: "andy",
age: 30
}
]
]
};
假设我们通过接口获取到如上数据,然后我们需要把如上的数据写入到页面里面,那么我们直接通过 this.form = copyData
只有第一层级的基础数据结构有效果(Boolean、String、Number),其他是没有效果的(Array,Object),也就是说,在多层级嵌套的情况下,我们需要通过 Vue 提供的上述 7 种方法,或者 $set
来设置响应式属性。
-
这次我们使用
$set
来完成响应式属性的设置。首先我们看
copyData
里面的list
,是一个数组,所以我们需要使用$set
来完成对数组的操作。你也可以使用 vm. s e t 实 例 方 法 , 该 方 法 是 全 局 方 法 V u e . s e t 的 一 个 别 名 : v m . set 实例方法,该方法是全局方法 Vue.set 的一个别名: vm. set实例方法,该方法是全局方法Vue.set的一个别名:vm.set(vm.items, indexOfItem, newValue)
上面的
vm.items
其实就是要设置的对象,indexOfItem
我们可以通过遍历list
来获取index
,newValue
就是对应的值。copyData.list.forEach((parent, index) => { this.$set(this.form.list, index, copyData.list[index]); });
通过以上代码,我们点击 test
按钮,发现页面会触发更新,同时渲染出对应的的内容。表明我们设置成功了,如果还有在深层次的嵌套,同样需要依次遍历对应的值,然后使用$set
设置即可。
表单验证
对于 element-ui 的表单验证,我们需要在 html 上添加一些属性
<div class="test">
<el-form ref="form" :model="form" label-width="80px" :rules="rules">
<div class="parent" v-for="(parent, index) in form.list" :key="`parent-${index}`">
<div class="child" v-for="(child, idx) in parent" :key="`child-${idx}`">
<el-form-item label="name" prop="name">
<el-input v-model="child.name"></el-input>
</el-form-item>
<el-form-item label="age">
<el-input v-model="child.age"></el-input>
</el-form-item>
</div>
</div>
</el-form>
<el-button type="primary" @click="testFun">test</el-button>
</div>
// ...script
// data
rules: {
name: {
required: true,
message: "请输入值",
trigger: "blur"
}
}
- 第一步,首先在
el-form
上,添加:rules="xxx"
,xxx 可以随便设置,这里我设置为rules
。 - 第二部,在要验证的表单
item
上,添加prop
,这个prop
对应rules
里面的值,这里设置为name
。
其实到这里已经设置完了,我们发现,在只有一个 name
表单的情况下,能够正常验证(没有通过 v-for 遍历),但是如果是多个表单同时都指向 name
呢 ?
所以我们可以在单个的表单域上传递属性的验证规则:
<el-form-item
label="name"
:prop="`list.${index}.${idx}.name`"
:rules="{ required: true, message: '请输入邮箱地址', trigger: 'blur' }">
<el-input v-model="child.name"></el-input>
</el-form-item>
在 rules
上,我们设置为单独的 rules
,而 prop
比较麻烦,需要以 index
和 .
的方式来取对应的字段,这里需要注意。
那么通过以上设置后,我们就可以对每个 name
字段分别进行验证了。
更多推荐
所有评论(0)