【⼿把⼿教你搓Vue响应式原理】(三)obrve以及__ob__
⼤家好,我是辉夜真是太可爱啦。这是我最近在写的【⼿把⼿教你搓Vue响应式原理】系列,本⽂将⼀步步地为你解开
vue响应式原理的⾯纱。由于本⼈也是在写这篇⽂章的过程中不断试错,不断学习改进的,所以,本⽂同样很适合和我⼀
样的初学者。和Vue的设计理念如出⼀辙,那就是渐进增强。
上⽂链接
【⼿把⼿教你搓Vue响应式原理】(⼀)初识Vue响应式
【⼿把⼿教你搓Vue响应式原理】(⼆)深度监测对象全部属性
前⾔
在上⼀⽂中,我们已经成功将深度对象(好⼏层的对象)成功遍历,全部绑定了
defineReactive
,也就是全部弄成了响应式对象。
虽然上述功能已经基本实现了对象的成功遍历,但是,在Vue的源码中,在我们遍历对象的同时,会将
newObrver()
创建的实例赋值到
__ob__
属性添加到每⼀个对象中。
这篇⽂章主要对标源码,新增了
__ob__
属性,以及
obrve
⼊⼝⽅法,相当于是对标源码,更规范地书写响应式。
这个
__ob__
属性,在vue使⽤中⼤家也可能有所眼熟,这篇⽂章本意也在于更规范地书写响应式。
并且,由于少了⼀个
obrve
⼊⼝⽅法,也是为了上⼀⽂中关于遍历对象添加
defineProperty
的写法更⽅便能被⼤家理解。
我们会将
__ob__
放在
Obrver
中,并且,将判断是否是对象放在
obrve
中,以及是否设置了
__ob__
属性,将
obrve
作为新的⼊⼝⽅
法。
整体的调⽤顺序如图:
上⽂代码
上⽂最终的代码如下:
functiondefineReactive(obj,key,val){
(key);
//判断当前⼊参个数,两个的话直接返回当前层的对象
if(===2){
val=obj[key];
typeofval==='object'&&newObrver(val);
}
Property(obj,key,{
//可枚举,默认为fal
enumerable:true,
//属性的描述符能够被改变,或者是删除,默认为fal
configurable:true,
get(){
returnval;
},
t(newValue){
val=newValue;
typeofval==='object'&&newObrver(val);
}
})
}
//遍历对象当前层的所有属性,并且绑定defineReactive
classObrver{
constructor(obj){
(obj);
}
walk(obj){
letkeys=(obj);
for(leti=0;i<;i++){
defineReactive(obj,keys[i])
}
}
}
__ob__
由于要遍历添加
__ob__
,所以,我们要先改写
Obrver
类,在构造函数中,新增对于
__ob__
属性的构建。
classObrver{
constructor(obj){
Property(obj,'__ob__',{
value:this,
//这个属性仅仅保存Obrver实例,所以不需要遍历
enumerable:fal
})
(obj);
}
//...
}
当然,我们可以对上⾯的代码进⾏⼀定的封装。
functiondef(obj,key,value,enumerable){
Property(obj,key,{
value,
enumerable
})
}
//遍历对象当前层的所有属性,并且绑定defineReactive
classObrver{
constructor(obj){
def(obj,'__ob__',this,fal)
(obj);
}
//...
}
obrve
既然现在有了
__ob__
属性,我们可以根据它是否有
__ob__
属性来判断它是否
newObrver
实例化过,⽽且可以将是否是对象的判断放在
obrve
⽅法中,将它作为⼊⼝⽂件。
现在的执⾏顺序应该是
obrve=>newObrve=>defineReactive
functionobrve(value){
if(typeofvalue!=='object')return;
letob;
//eslint-disable-next-lineno-prototype-builtins
if(Property('__ob__')&&value.__ob__instanceofObrver){
ob=value.__ob__;
}el{
ob=newObrver(value);
}
returnob;
}
由于我们已经将是否对象的判断放⼊了
obrve
中,所以,需要将之前的
typeofval==='object'&&newObrver(val);
改为
obrve(val)
。
所以,最终的代码如下:
functiondefineReactive(obj,key,val){
(key);
//判断当前⼊参个数,两个的话直接返回当前层的对象
if(===2){
val=obj[key];
obrve(val)
}
Property(obj,key,{
//可枚举,默认为fal
enumerable:true,
//属性的描述符能够被改变,或者是删除,默认为fal
configurable:true,
get(){
returnval;
},
t(newValue){
val=newValue;
obrve(val)
}
})
}
functiondef(obj,key,value,enumerable){
Property(obj,key,{
value,
//这个属性仅仅保存Obrver实例,所以不需要遍历
enumerable
})
}
//遍历对象当前层的所有属性,并且绑定defineReactive
classObrver{
constructor(obj){
def(obj,'__ob__',this,fal)
(obj);
}
walk(obj){
letkeys=(obj);
for(leti=0;i<;i++){
defineReactive(obj,keys[i])
}
}
}
functionobrve(value){
if(typeofvalue!=='object')return;
letob;
//eslint-disable-next-lineno-prototype-builtins
if(Property('__ob__')&&value.__ob__instanceofObrver){
ob=value.__ob__;
}el{
ob=newObrver(value);
}
returnob;
}
下⽂引荐
【⼿把⼿教你搓Vue响应式原理】(四)数组的响应式处理
【⼿把⼿教你搓Vue响应式原理】(五)Watcher与Dep
本文发布于:2022-11-23 08:19:24,感谢您对本站的认可!
本文链接:http://www.wtabcd.cn/fanwen/fan/90/4660.html
版权声明:本站内容均来自互联网,仅供演示用,请勿用于商业和其他非法用途。如果侵犯了您的权益请与我们联系,我们将在24小时内删除。
留言与评论(共有 0 条评论) |