vue动态数据绑定1--如何监听一个对象的变化

本文探讨Vue的动态数据绑定原理,通过学习源码,介绍如何监听对象属性的变化。文章详细阐述了Observer构造函数的实现,包括如何为对象属性添加get和set方法,以及如何处理深层次的对象属性,确保所有层级的属性变化都能被跟踪。最终展示了一个成功响应getter和setter的例子。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

之前经常使用 Vue,后来不满足于仅仅使用它,我想了解其内部实现原理,所以就尝试学习其源码,获益匪浅。
- 动态数据绑定就是 Vue 最为基础,最为有用的一个功能。给定任意一个对象,如何监听其属性的读取与变化?也就是说,如何知道程序访问了对象的哪个属性,又改变了哪个属性? 举个例子。

let app1 = new Observer({
  name: 'yyy',
  age: 20
});

let app2 = new Observer({
  university: 'uestc',
  major: 'computer'
});

// 要实现的结果如下:
app1.data.name // 你访问了 name
app.data.age = 100;  // 你设置了 age,新的值为100
app2.data.university // 你访问了 university
app2.data.major = 'science'  // 你设置了 major,新的值为 science

实现这样的一个 Observer,要求如下:

  1. 传入参数只考虑对象,不考虑数组。
  2. new Observer返回一个对象,其 data属性要能够访问到传递进去的对象。
  3. 通过 data 访问属性和设置属性的时候,均能打印出对应的信息。
  4. 如果传入参数对象是一个“比较深”的对象(也就是其属性值也可能是对象),那该怎么办。

要实现上述目标,首先要定义一个对象的构造函数,然后定义原型方法,遍历对象本身的各个属性,并为每个属性绑定get和set方法。考虑到第4个问题,在程序中加入了递归的思想。
实现代码如下:

// 首先定义观察者构造函数
function Observer(data){
    this.data=data;
    this.walk(data);
}

// walk()函数用于深层次遍历对象的各个属性
// 采用的是递归的思路
// 因为我们要为对象的每一个属性绑定get和set
Observer.prototype.walk = function(obj){
    let val;
    for(let key in obj){
        // 这里为什么要用hasOwnProperty进行过滤呢?
        // 因为for...in 循环返回的是对象原型链上的所有能够通过对象访问的、可枚举的属性
        // hasOwnProperty只在属性存在于实例中时才返回true
        // 而我们想要的正是这个对象本身拥有的属性,所以要这么做。
        if(obj.hasOwnProperty(key)){
            val = obj[key];
            // 这里进行判断,当访问的属性是一个对象时,继续new Observer,直到到达最底层的属性位置
            if(typeof val ==='object'){
                new Observer(val);
            }
            this.convert(key,val);
        }
    }
};
// 以自定义get和set函数
Observer.prototype.convert = function(key,val){
    Object.defineProperty(this.data,key,{
        enumerable:true,
        configurable:true,
        get:function(){
            console.log('你访问了'+key);
            return val;
        },
        set:function(newVal){
            console.log('你设置了'+key);
            console.log('新的'+key+'='+newVal);
            if(newVal===val) return;
            // 如果设置新的值是一个对象的话,继续new Observer,直到到达最底层的属性位置
            if(typeof newVal === "object"){
                new Observer(newVal);
            };
            val = newVal;
        }
    })
};
let data={
    user:{
        name: "yjm",
        age: "21"
    },
    address: "成都"
};
let app =new Observer(data);
  • 当访问的属性是一个对象的时候,对这个对象属性进行new Observer,直到到达最底层的属性位置,使‘深层次’的属性也能被访问到。
  • 同时为对象设置setter的时候,如果设置新的值是一个对象的话,也继续new Observer,直到到达最底层的属性位置,使新设置的值对象的子属性也能继续响应 getter 和 setter。
    效果如下:

这里写图片描述
这里写图片描述
这里写图片描述
如上图所示:无论是访问一个简单值或者是一个深层次的对象,都可以很好响应getter 和 setter。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值