今天发现,某对话框打开后,其中的input无法接收键盘输入,我在页面上劈里啪啦敲了一堆,页面输入框空空如也,的确是用了v-model来实现双向绑定。但是显然,它没有实现双向数据传输。那么,双向数据传输除了使用v-model之外,还有其他的条件么?
查看vue2官网深入响应式原理章节深入响应式原理 — Vue.js,其中有这么一段:
我这个正好是一个form表单中的控件,绑定的是一个对象中的属性:form.projectName
<el-input v-model="form.projectName" placeholder="请输入项目标题"/><br>
<input type="text" v-model="form.projectName"/>
对象
于是,继续向下看:
回去仔细看了我的代码:
data中确实在form中定义了projectName, 按道理应该没问题;
但是,我写了个reset函数,其中重新定义了一个form对象,覆盖了data中的form
reset(){
this.form = {
}
}
这就导致在执行了reset之后,这个属性从响应式变成了非响应式。
根据官网的说法,有两种修正方式
1、使用对form中对象属性赋值为null的方法来重置,而不是重新定义form对象
this.form.projectName = null;
2、使用官网中推荐的为对象添加属性的方式
this.$set(this.form,'projectName',null);
数组
同理,Vue 不能检测以下数组的变动:
- 当你利用索引直接设置一个数组项时,例如:
vm.items[indexOfItem] = newValue
- 当你修改数组的长度时,例如:
vm.items.length = newLength
当通过以上方式来修改数组项的数据或数组长度时,页面上与该数据项或数组长度绑定的控件无法正确更新。
例如,我曾经遇到的问题是:table中的某一列是通过一个数组对象拼接成的逗号分隔的字符串,当我通过交互控件,从页面上修改了这一列的数据时,通过console可以看到data中的数据更新了,但是页面上table中的内容没更新,也就是说,vue未能监测到Model中这个数据项的变化,因而没有通知View进行更新。
对于问题1,可以使用以下两种方式解决(我习惯用1,跟对象一样的形式,好记):
Vue.$set(vm.items, indexOfItem, newValue) / vm.$set(vm.items, indexOfItem, newValue)
或
vm.items.splice(indexOfItem, 1, newValue)
对于问题2:
vm.items.splice(newLength)