title: Vue 更新data选项中的数组
date: 2018-12-18 18:05:19
tags: [Vue]
categories: Vue
疑问
最近看到一道面试题,如下:
var vm = new Vue({
data: {
items: [1, 2, 3]
}
})
vm.items[1] = 'x'
vm.items.length = 2
这样写有什么问题?那应该怎么写?
我看到这道题时并不觉得有什么问题。在Vue中,一旦响应式数据发生改变,setter 不是会发通知给 watcher 吗?
解答
后来我才知道,这样子写的话 Vue 不会更新该数组数据对应的视图。
请先阅读完官方文档的 深入响应式原理,再看下面:
- 数据确实更新了,但视图没有更新,那就说明 Vue 并没有检测到该数据更新了
- 其实是数组的问题,在 Vue 中它比较特殊。
- 我们知道,Vue 会在初始化实例时对属性执行
getter/setter
转化过程,所以属性必须在 data 对象上存在才能让 Vue 转换它,这样才能让数据是响应式的。 - 往深了说,其实 Vue 在我们的data对象上都会定义一个ob属性指向新创建的Observer对象,以此对数据设置监控器。但由于现代 JavaScript 的限制(底层原理不明),
Object.Observe
支持的不好,Vue 无法对数组进行Observer对象创建,因此不能检测到数组对象的变化。 - 不过 Vue 给我们提供了别的方法,具体见下面。
解决方法
// Vue.set
Vue.set(vm.items, indexOfItem, newValue)
// Array.prototype.splice
vm.items.splice(indexOfItem, 1, newValue)
vm.items.splice(newLength)