关于vue2没有在data中定义的属性非响应式的问题
- vue2 响应式的原理及实现
- vue2 解决此类的部分
vue2 响应式的原理及实现
vue2 响应式数据 是通过 es5 中的 Object.defineProperty 方法来实现,把 data 定义的所有属性,转换为 get/set 方法,使用 Object.defineProperty 方法劫持
步骤:
- 遍历data中的所有属性转换为 get/set ,使用 Object.defineProperty 劫持
- 当data中定义的属性改变时 会触发 set 方法 通知 watcher 从而使它关联的组件重新渲染
由此可见 图中定义了 data 对象 , 并且使用 Object.defineProperty 方法劫持了 data 对象中的 page 属性,在控制台分别输出了 data.page 和 data.name 的值
data.page 返回的值 后面还加上了 《后缀》 ,因为在 get 方法中 对字符串返回做了二次处理
回归正题 因为 vue 实例在加载 data 对象时 已经把 data 中的值 使用 Object.defineProperty 遍历过一遍, 当下次,直接使用 data[新属性] 这时 新属性是没有转化为 get/set使用 Object.defineProperty 劫持, 所以当这个新属性 的值 改变时,并不会触发视图变更,如下图
在控制台可见 course 对象是已经改变了的 但是 视图上却 没变更。
vue2 解决此类的部分
- 需要响应式的数据都在data中先声明
- 使用 this.$set 方法 Vue.set(object, propertyName, value)
如果data 中的一个对象 里面有很深的层级 ,并且有很多是前期不好声明的,而且我们一开始只能定义一个变量的名字 course ,那么接下来 全部使用 $set 方法来实现响应式 ,显然是比较繁琐的
解决办法 在 course 已经改变完成之后 里面那些没有前期定义的属性非响应式的 ,在最后把 course 重新生成一个新对象 再赋值给 course ,因为course最开始已经在data中定义了,当course改变会触发 defineProperty 方法,从而渲染视图