进行代理(解决第一步读写数据调用函数)
vue2使用Object.defineProperty进行数据代理(getter和setter),vue3使用Proxy进行数据代理
Proxy的性能会比Object.defineProperty好很多
- Object.defineProperty是一次性代理完所有的数据,如果对象嵌套很深就会一直递归直到代理完所有属性
- Proxy是动态代理的,当读取属性是对象的时候才会继续进行代理(刚开始只代理最外面的一层)
- Object.defineProperty在代理完成之后再添加属性是不能监听到的,所以vue2有 s e t 和 set和 set和delete
- 因为Proxy代理的是整个对象所以后续添加属性可以监听到,所以vue3删除了
s
e
t
和
set和
set和delete
记录依赖/派发更新(但是不知道是哪个函数用了我)
- getter
- 在getter时记录依赖(记录谁用到了我)
- setter
- 在setter时派发更新(把依赖这个数据的函数重新运行重新运行函数的时候会再次收集依赖)
哪个函数依赖了数据
vue在全局中写了一个用来运行函数的函数,有一个全局变量保存当前运行的是哪个函数,这样在getter的时候只要检查这个全局变量就知道是哪个函数在使用这个变量了,vue还建立了一个对映关系表当setter的时候把对映表中的函数重新运行一遍(收集依赖收集的是函数运行的环境不单单是函数,因为当后续)
// 函数运行环境 function effect(fn) { const effectFn = () => { // 保存当前的effectFn方便在数据更新后再运行函数时的依赖收集中找到是哪个函数 activeEffect = effectFn; fn(); // 清空当前的effect activeEffect = null; }; effectFn(); }
异步更新队列
如果每次数据改变都进行渲染的话那渲染的性能就会很差,所以有了异步数据渲染nextTick,当需要派发更新的时候不会立即运行函数,而是交给nextTick,nextTick会把函数放入异步队列,同一个渲染函数只会存在一个,这样就不会多次渲染造成效率问题
- 在setter时派发更新(把依赖这个数据的函数重新运行重新运行函数的时候会再次收集依赖)
- getter
还没有评论,来说两句吧...