vue2和vue3都重写了数组方法
vue2和vue3都重写了数组方法
vue2的defineProperty
1 | function defineReactive(obj, key) { |
defineProperty利用闭包, 对_val进行set和get,称为数据劫持。
- defineProperty的缺陷
由此可见defineProperty的响应式粒度是key级别的。也就是说,已知的属性才有办法劫持其getter和setter,所以其根本没有办法对未知的key劫持做响应。
- 为什么vue2不对数组进行劫持?而是重写数组方法?
在vue2直接通过下标修改数组是不会响应式更新的。
1 | arr[0] = 'xxx' //× |
原因:
- 数组如果很大,会产生大量闭包,耗费大量内存。
- 一般开发者只关心数组本身的变化,而不关心每个元素内部的变化。而这些数组方法恰好只关注数组本身的变化。
- 要对数组劫持的话,对于未知的key无法配置getter和setter。
- 那为什么对象就劫持了呢?
因为对象和数组关注点不同,数组自身可能变化;而对象自生一般不变化,关注属性的变化。
vue3的重写数组方法
基于Proxy
实现响应式,其粒度在对象级别, 所以对于未知的key也能实现响应式。
1 | function reactive(target) { |
- vue3还要重写数组方法?
因为利用Proxy
返回的是代理对象,和原本对象不相等。所以需要重写一些查找相关的方法。
但是vue3还重写了一些修改相关的方法。为什么,有必要吗?
因为调用push等方法会
- 访问push属性
- 访问length属性
- 修改length属性
当访问length属性也被收集做依赖,那么接下来修改length会导致此方法被无限调用
- 而且Vue3代理是惰性的
不像defineProperty一样需要先遍历所有key,对所有key做劫持。而是读到该属性为对象时才会递归reactive
1 | function reactive(target) { |