直接操作 Vue data 中不存在的属性导致的 v-model 绑定异常问题
初学Vue遇到的问题,尝试了几个小时才搞明白,大佬应该一眼就能看出什么问题吧……
需要注意,不要直接在JS中操作一个Vue data对象中不存在的属性,如果同时有通过v-model
绑定到该对象的不存在的属性时,会出现诡异的行为表现,console
中不会报出任何 warn
或 error
。
需求是,实现三个复选框,第一个复选框初始为选中状态,一开始写出来是这样的——
1 | <div id="app" style="margin: 10px;"> |
1 | new Vue({ |
试下效果:
See the Pen vue-v-model-not-work by iMaeGoo (@iMaeGoo) on CodePen.
复选框a的表现显然是异常的,点击不能成功地切换选中状态,而在点击之后再点击其他复选框,才会“有延迟地”切换状态。
为什么会这样?
尝试在created
方法的末尾打印出this.checkboxes[0]
——
发现 id
和 title
都变成了 getter/setter 的形式,而 selected 仍然是独立的属性。
后续查询发现,Vue 官方文档 - 深入响应式原理 的第一段话是——
当你把一个普通的 JavaScript 对象传入 Vue 实例作为
data
选项,Vue 将遍历此对象所有的属性,并使用Object.defineProperty
把这些属性全部转为getter/setter
。Object.defineProperty
是 ES5 中一个无法 shim 的特性,这也就是 Vue 不支持 IE8 以及更低版本浏览器的原因。
在 created
方法中,我尝试直接对 Vue data 对象中的属性操作,而 v-model
需要使用 getter/setter
操作,二者即产生了冲突。
解决方式 1
在 data 中添加 selected 属性,即使初值为undefined
或者null
,也能够让 Vue 正确识别所有对象属性。
1 | data () { |
解决方式 2
在JS中操作原本不存在的属性时,使用 Vue.set(object, propertyName, value) 方法向嵌套对象添加响应式属性
1 | created () { |
直接操作 Vue data 中不存在的属性导致的 v-model 绑定异常问题