Observe 源码解析 劫持Object对象 监听数据变化

发布时间:2024年01月03日
/**
 * 可以帮我们事先对对象里面的所有属性进行劫持
 * */ 
class Observe{
    constructor(obj){
        this.observe(obj)
    }
    observe(obj){
        if(obj&&typeof obj=='object'){
            for(let attr in obj){
                this.defineReactive(obj,attr,obj[attr])
            }
        }
    }
    /**
     * obj待处理的对象
     * attr 对象的属性
     * value 进行get/set 操作的是value
     * */ 
    defineReactive(obj,attr,value){
        this.observe(value);//对value需要进一步的进行劫持
        Object.defineProperty(obj,attr,{
            get(){
                return value;
            },
            set:(newValue)=>{
                if(value!==newValue){
                    this.observe(newValue);//判断新设置的值是否是对象,如果是对象,也需要被劫持
                    value=newValue;
                    console.log('set操作,数据变化了,视图进行更新',newValue);
                }
            }
        })
    }
}
    <script>
        const obj={
            id:1,
            name:'andy',
            age:{
                n:23
            }
        }
       
        new Observe(obj)
        obj.age={
            n:50}
        obj.age.n=54
        console.log(obj);
    </script>

?代码解析?

1.constructor构造函数

?constructor(obj){
? ? ? ? this.observe(obj)
? ? }

是初始化Observe类,将所传入类的参数,可以通过constructor参数的obj中获取

这里的this是代表Observe这个类的this,调用这个类里面的observe方法

2.observe方法定义逻辑

? ? observe(obj){
? ? ? ? if(obj&&typeof obj=='object'){
? ? ? ? ? ? for(let attr in obj){
? ? ? ? ? ? ? ? this.defineReactive(obj,attr,obj[attr])
? ? ? ? ? ? }
? ? ? ? }
? ? }

是对象与数组劫持所以首先判断传入的类型,是否符合

通过for in的方式将,对象的key,value,对象遍历出来,循环调用defineReactive,将数据传入

3.数据劫持关键代码

?defineReactive(obj,attr,value){
? ? ? ? this.observe(value);//对value需要进一步的进行劫持
? ? ? ? Object.defineProperty(obj,attr,{
? ? ? ? ? ? get(){
? ? ? ? ? ? ? ? return value;
? ? ? ? ? ? },
? ? ? ? ? ? set:(newValue)=>{
? ? ? ? ? ? ? ? if(value!==newValue){
? ? ? ? ? ? ? ? ? ? this.observe(newValue);?
? ? ? ? ? ? ? ? ? ? value=newValue;
? ? ? ? ? ? ? ? ? ? console.log('set操作,数据变化了,视图进行更新',newValue);
? ? ? ? ? ? ? ? }
? ? ? ? ? ? }
? ? ? ? })
? ? }

(1).先看Object.defineProperty

get是监听获取对象中值的时候,会执行

set是监听设置的时候会执行

为什么在set箭头函数内,再次调用this.observe是因为放置所设置的值是对象,若是对象则继续执行监听,不是则停止,observe有判断拦截

(2).一开始上来就先调用this.observe(value)

因为对象内也可以再声明对象,若没有再次以递归的方式调用一次,则无法监听,多个对象执行修改

如下:

new Observe(obj)
obj.age={n:50}
obj.age.n=54

文章来源:https://blog.csdn.net/qq_41429765/article/details/135345626
本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。