力有不逮的对象
众所周知,在 Vue 中,直接修改对象属性的值无法触发响应式。当你直接修改了对象属性的值,你会发现,只有数据改了,但是页面内容并没有改变。
这是什么原因?
原因在于: Vue 的响应式系统是基于Object.defineProperty
这个方法的,该方法可以监听对象中某个元素的获取或修改,经过了该方法处理的数据,我们称其为响应式数据。但是,该方法有一个很大的缺点,新增属性或者删除属性不会触发监听,举个栗子:
var vm = new Vue({ data () { return { obj: { a: 1 } } }})// `vm.obj.a` 现在是响应式的vm.obj.b = 2// `vm.obj.b` 不是响应式的
原因在于,在 Vue
初始化的时候, Vue
内部会对 data
方法的返回值进行深度响应式处理,使其变为响应式数据,所以, vm.obj.a
是响应式的。但是,之后设置的 vm.obj.b
并没有经过 Vue
初始化时响应式的洗礼,所以,理所应当的不是响应式。
那么,vm.obj.b
可以变成响应式吗?当然可以,通过 vm.$set
方法就可以完美地实现要求,在此不再赘述相关原理了,之后应该会写一篇文章讲述 vm.$set
背后的原理。
更凄惨的数组
上面说了这么多,还没有提到本篇文章的主角——数组,现在该主角出场了。
比起对象,数组的境遇更加凄惨一些,看看官方文档:
由于 JavaScript 的限制, Vue 不能检测以下变动的数组:
vm.items[indexOfItem] = newValue
当你修改数组的长度时,例如:vm.items.length = newLength
有可能官方文档不是很清晰,那我们继续举个栗子:
var vm = new Vue({ data () { return { items: ['a', 'b', 'c'] } }})vm.items[1] = 'x' // 不是响应性的vm.items.length = 2 // 不是响应性的
也就是说,数组连自身元素的修改也无法监听,原因在于, Vue 对 data 方法返回的对象中的元素进行响应式处理时,如果元素是数组时,仅仅对数组本身进行响应式化,而不对数组内部元素进行响应式化。
这也就导致如官方文档所写的后果,无法直接修改数组内部元素来触发响应式。
那么,有没有破解方法呢?
当然有,官方规定了 7 个数组方法,通过这 7 个数组方法,可以很开心地触发数组的响应式,这 7 个数组方法分别是:
push() pop() shift() unshift() splice() sort() reverse()可以发现,这 7 个数组方法貌似就是原生的那些数组方法,为什么这 7 个数组方法可以触发应式,触发视图更新呢?
新闻热点
疑难解答
图片精选