在看这篇文章之前希望大家还是有一定的基础,能够了解Vue2的一些基础原理,了解Proxy代码的基础应用以及WeakMap,Map,Set这些数据结构的特性。如果对这些还不了解的同学建议先去补一下基础知识。
如果你对vue3还不了解建议先去学习下vue3。
vue3基础特性
vue3+Ts实战
声明: 本文中采用的方法名均为源码中的方法名,很多代码结构按照源码的结构来写的,目的就是在于希望能够对想看源码的同学做一些引导。
如果代码中有些地方你不能一下子想明白的,先尝试去接受它,然后回过头来再去理解它。
重中之重:对于本文的学习方式上希望大家一定要更着去手写代码,多做一些思考,看完之后我相信你一定会有所收获。
如果有什么不对的地方也欢迎大家留言指正。
响应式
我们都知道vue2中是通过defineProperty
实现对数据的拦截监听,而vue3中采用的Proxy
,相较于defineProperty
,即能监听数组,不需要进行嵌套,不用遍历每个属性,针对整个对象更加轻便。
vue3通过reactive
创建一个响应式对象,当对象被修改的时候,视图也会随着更新,对应的副作用函数也会执行(这个我们后面实现watchEffect
的时候再分析)。这其中主要有两个过程:
- 对数据进行监听并收集依赖
- 更新视图(后话)
而reactive
内部就是通过Proxy
实现对数据的拦截监听。
// v3.js
// reactive 的实现
function reactive(target){
return createReactiveObject(
target,
mutableHandlers
);
}
/**
* 真正创建响应式对象的函数
* @param {*} target 对象
* @param {*} handler 处理程序
*/
function createReactiveObject(target,handler){
const proxy = new Proxy(target,handler);
return proxy;
}
Proxy
对数据的监听主要在handler
中进行处理, handler
是一个定义一个或多个陷阱的对象。接着我们实现一下mutableHandlers
对象
// v3.js
const get = createGetter();
function createGetter(){
return function get(target,key,receiver){
const res = Reflect.get(target, key, receiver);
console.log('get执行了',key);
return res;
}
}
const set = createSetter();
function createSetter(){
return function set(target,key,value,receiver){
const res = Reflect.set(target,key,value,receiver);
console.log('set执行了',key);
return res;
}
}
// proxy的处理程序,是一个定义一个或多个陷阱的对象
// 只处理简单的 get 和 set
const mutableHandlers = {
get,
set
}
// reactive 的实现
function reactive(target){
return createReactiveObject(
target,
mutableHandlers
);
}
/**
* 真正创建响应式对象的函数
* @param {*} target 对象
* @param {*} handler 处理程序
*/
function createReactiveObject(target,handler){
const proxy = new Proxy(target,handler);
return proxy;
}
这样我们就实现了一个简单的reactvie
,能够对数据进行监听了。可以通过以下代码测试一下:
// v3.js
const testObj = reactive({ count:10 }})
testObj.count
testObj.count = 20
// 通过node v3.js执行当前代码
// get执行了 count
// set执行了 count
这只是实现了对简单对象的监听,如果对象复杂一点,就会存在问题,例如:
// v3.js
const testObj = reactive({ count:10, info: { name:'lucas' }})
testObj.info.name
testObj.info.name = 'viky'
// 执行结果如下
// get执行了 count
// set执行了 count
这样监听就失效了,没有监听到name
属性,优化一下get
方法,如果当值为对象的时候,我们应该递归监听:
// v3.js
const isObject = (target)=>{ return target !== null && typeof target === 'object'}
function createGetter(){
return function get(target,key,receiver){
const res = Reflect.get(target, key, receiver);
console.log('get执行了',key);
if(isObject(res)){
return reactive(res);
}
return res;
}
}
到这里我们的reactive
已经实现了对数据的监听。
订阅
接下来我们开始收集依赖,依旧是在get中进行处理,通过track
函数进行依赖收集,在这之前先大致介绍一下vue3中用于存储依赖的数据结构。
常见问题FAQ
- 免费下载或者VIP会员专享资源能否直接商用?
- 本站所有资源版权均属于原作者所有,这里所提供资源均只能用于参考学习用,请勿直接商用。若由于商用引起版权纠纷,一切责任均由使用者承担。更多说明请参考 VIP介绍。
- 提示下载完但解压或打开不了?
- 找不到素材资源介绍文章里的示例图片?
- 模板不会安装或需要功能定制以及二次开发?
发表评论
还没有评论,快来抢沙发吧!