前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >Vue3.0 beta源码学习笔记(一)

Vue3.0 beta源码学习笔记(一)

作者头像
用户7572539
发布2020-08-26 11:07:36
3650
发布2020-08-26 11:07:36
举报

今天开始总结学习Vue3.0的基本原理。(reactive笔记)

在Vue3.0中将响应式处理放到reactivity文件夹中,然后将其中的reactive,effect,computed, ref各自抽离分模块编写。首先记录一下创建相应数据的reactive方法。

首先在使用reactive方法创建响应式对象时,需要传入一个目标对象:

1const state = reactive({name : "DreamYI",age : 22})

所以在实现reactive(target)方法时应该基于目标对象进行响应式对象的创建,但是目标对象可能不仅仅是一个普通对象、数组还有可能是set map,所以在处理普通的对象和数组时可以在reactive中自定义并返回一个创建响应式数据的方法createReactiveObject(target,mutableHandler)。

代码语言:javascript
复制
1export function reactive(target){
2 // 创建一个响应式的对象 目标对象可能不一定是数组或者对象 可能还有 set map
3 return createReactiveObject(target,mutableHandler);
4}

下面来实现这个创建响应式数据的方法:

代码语言:javascript
复制
1function createReactiveObject(target,baseHandler){
2 if(!isObject(target)){ // 不是对象直接返回即可  isObject为自定义的工具函数判断参数是否为对象
3 return target;
4    }
5 const observed = new Proxy(target,baseHandler);
6 return observed;
7}

这个函数中返回了代理的对象,下面来实现代理的具体处理过程,实现最基本的访问、修改拦截。也就是填补mutableHandler参数的get set操作。在此之前可以将mutableHandler的实现抽离出来。

代码语言:javascript
复制
1//拦截普通对象的处理
2export const mutableHandler = {
3    get,
4    set,
5 // 除了代理这些方法之外 可能还有很多逻辑 deleteProperty has...
6}

在这个参数对象里我们可以对目标对象做很多的拦截操作,这里只简单实现get set。为了代码简洁,将get set抽离单独编写。

代码语言:javascript
复制
 1const get = createGetter();
 2const set = createSetter();
 3// proxy + reflect => es6 的api
 4function createGetter() {
 5 return function get(target, key, receiver) { // proxy + reflect
 6 const res = Reflect.get(target, key, receiver); // target[key];
 7 // todo..
 8 console.log('用户对这个对象取值了',target,key);  
 9 return res
10    }
11}
12
13function createSetter() {
14 return function set(target, key, value, receiver) { 
15 const result = Reflect.set(target, key, value, receiver); // target[key] = value
16 // todo... 
17 console.log('用户对这个对象取值了',target,key);
18 return result;
19    }
20}

现在已经对普通对象进行了基本的数据拦截

1用户对这个对象取值了 {name: "DreamYi", age: 22} name 2用户对这个对象取值了 {name: "duan", age: 22} name

但是此时在传入target是如果有数组元素时:

代码语言:javascript
复制
1const state = reactive({ name: "DreamYi", age: 22 ,arr:[1,2,3]})
2state.arr.push(4)

并且调用数组的push方法:

1用户对这个对象取值了 {name: "duan", age: 22, arr: Array(3)} arr

结果表示:的确是取到了数组arr 但是并没有增加元素4

这是因为此时取到的arr还是一个普通的数组并不是响应式数据,所以此时需要再次对取到的对象做代理执行reactive():

代码语言:javascript
复制
 1function createGetter() {
 2 return function get(target, key, receiver) { // proxy + reflect
 3 const res = Reflect.get(target, key, receiver); // target[key];
 4 // todo..
 5 console.log('用户对这个对象取值了',target,key); 
 6 if (isObject(res)) {
 7 return reactive(res)
 8        }
 9 return res
10    }
11}

此时的结果:

1用户对这个对象取值了 {name: "duan", age: 22, arr: Array(3)} arr 2baseHandlers.js:13 用户对这个对象取值了 (3) [1, 2, 3] push 3baseHandlers.js:13 用户对这个对象取值了 (3) [1, 2, 3] length 4baseHandlers.js:29 修改操作 (4) [1, 2, 3, 4] 3 5baseHandlers.js:29 修改操作 (4) [1, 2, 3, 4] length

但是现在会触发两次修改的操作,对于length属性的操作是没有意义的,所以希望把他屏蔽掉:

代码语言:javascript
复制
 1function createSetter() {
 2 return function set(target, key, value, receiver) {
 3 // 需要判断是修改属性 还是增加属性 ,如果原来的值 和新设置的值一样什么都不做
 4 const hadKey = hasOwn(target, key);
 5 const oldValue = target[key];
 6 const result = Reflect.set(target, key, value, receiver); // target[key] = value
 7 // todo... 
 8 if (!hadKey) {
 9 console.log('属性的新增操作',target,key); 
10        } else if (hasChanged(value, oldValue)) {
11 console.log('修改操作',target,key); 
12        }
13 // 值没有变化什么都不用做
14 return result;
15    }
16}

hadKey()、hasChanged()分别是判断对象中是否存在某个属性,与对象是否发生变化的工具函数;

此时要判断是增加属性还是修改属性,所以如果新址值与旧值一样 那就什么都不用做;此时结果:

1用户对这个对象取值了 {name: "DreamYi", age: 22, arr: Array(3)} arr 2baseHandlers.js:13 用户对这个对象取值了 (3) [1, 2, 3] push 3baseHandlers.js:13 用户对这个对象取值了 (3) [1, 2, 3] length 4baseHandlers.js:30 属性的新增操作 (4) [1, 2, 3, 4] 3

此时的新增操作只有索引3;

在vue3.0版本中并不是直接对传入的目标对象进行深度的递归,而是在取值的时候进行代理,也解决了vue2.x版本中不能及时对数组索引变化做响应式处理的问题,在性能上得到了很大的提升。

至此,就实现了vue3.0中简单的代理功能。

本文参与 腾讯云自媒体分享计划,分享自微信公众号。
原始发表:2020-06-30,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 二少爷的花间集 微信公众号,前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体分享计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档