程序员的知识教程库

网站首页 > 教程分享 正文

前端基础:为什么vue更新数组时能够触发视图更新?方法有哪些?

henian88 2024-08-27 15:51:11 教程分享 5 ℃ 0 评论

变异方法(去改变原数组):

Vue 包含一组观察数组的变异方法,所以它们也将会触发视图更新。这些方法如下:

  1. push()
  2. pop()
  3. shift()
  4. unshift()
  5. splice()
  6. sort()
  7. reverse()

为什么Vue官方文档只列举了这几个操作数组的方法?

替换数组(新数组覆盖原数组):

filter(), concat()和 slice() 。这些不会改变原始数组,但总是返回一个新数组。当使用这些非变异方法时,可以用新数组替换旧数组:

example1.items = example1.items.filter(function (item) {
 return item.message.match(/Foo/)
})

为什么返回一个新数组也可以触发视图更新?


我们知道,由于 JavaScript 的限制,Vue 不能检测以下变动的数组:

1.当你利用索引直接设置一个项时,例如:vm.items[indexOfItem] = newValue

2.当你修改数组的长度时,例如:vm.items.length = newLength

举个例子:

var vm = new Vue({
 data: {
 items: ['a', 'b', 'c']
 }
})
vm.items[1] = 'x' // 不是响应性的
vm.items.length = 2 // 不是响应性的

这是为什么呢?

这就要回到Vue的响应式原理:Object.defineProperty(obj, prop, descriptor)

,这个方法只能检测属性的变化.

举个例子:

var a = {};
bValue = 1;
Object.defineProperty(a, "b", {
 set: function(value) {
 bValue = value;
 console.log("setted");
 },
 get: function() {
 return bValue;
 }
});
a.b; //1
a.b = []; //setted
a.b = [1, 2, 3]; //setted
a.b[1] = 10; //无输出
a.b.push(4); //无输出
a.b.length = 5; //无输出
a.b; //[1,10,3,4,empty];

可以看出,a.b=[]或a.b=[1,2,3]等直接赋值引用类型是可以打印setted,即可以调用set方法。其他修改可以改变a.b的值,但无法调用set。这也是上述所说的"JavaScript 的限制",而不是Vue自身原因。

因此,变异方法的7个方法是Vue内部改造了,所以可以触发视图更新;替换数组的3个方法类似:

a.b = []; //setted
a.b = [1, 2, 3]; //setted

进行覆盖,引用类型是可以触发setter,因此也可以触发视图更新。

另外:Vue文档说,Vue 为了使得 DOM 元素得到最大范围的重用而实现了一些智能的、启发式的方法,所以用一个含有相同元素的数组去替换原来的数组是非常高效的操作。

(个人猜测,未验证:假如a.b=[1,2,3,4,5,6,7,8,9],采用filter取偶数之后,a.b=[2,4,6,8]。那么新的数组元素2,4,6,8原数组中的key保持不变,所以可以高效渲染DOM,至于怎么保持key不变,应当就是原文档的表述“最大范围的重用而实现了一些智能的、启发式的方法”,这个查阅源码才知道呢......

Tags:

本文暂时没有评论,来添加一个吧(●'◡'●)

欢迎 发表评论:

最近发表
标签列表