前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >vue源码讲解----数据响应式原理

vue源码讲解----数据响应式原理

作者头像
zhouzhouya
发布2023-10-27 16:07:58
1500
发布2023-10-27 16:07:58
举报
文章被收录于专栏:一名前端开发一名前端开发

数据响应式原理是我们在开发过程中一定要了解的知识,彻底搞懂数据响应式原理,刻不容缓。

Object.defineProperty()方法

首先我们应该知道Vue采用数据劫持 + 发布者-订阅者模式实现双向数据绑定, 然后我们来看一下Object.defineProperty()方法,此方法会直接在对象上定义属性,或者修改一个对象的现有属性,并返回此对象

代码语言:javascript
复制
let obj = {};  
Object.defineProperty(obj, 'a', {  
    value: 1 
});  
Object.defineProperty(obj, 'b', {  
    value: 2 
});  
console.log(obj);   //{a:1,b:2}
console.log(obj.a, obj.b); //1,2

Object.defineProperty()方法还可以设置一些额外的隐藏属性。

代码语言:javascript
复制
Object.defineProperty(obj, 'a', {  
    value: 1 ,
    // 是否可写  
    writable: false
});  
Object.defineProperty(obj, 'b', {  
    value: 2 ,
   // 是否可以被枚举  
    enumerable: false
}); 

getter和setter

get 属性的 getter 函数,如果没有 getter,则为 undefined。当访问该属性时,会调用此函数。执行时不传入任何参数,但是会传入 this 对象 (由于继承关系,这里的 this 并不一定是定义该属性的对象)。该函数的返回值会被用作属性的值。默认为 undefined。 set 属性的 setter 函数,如果没有 setter,则为 undefined。当属性值被修改时,会调用此函数。该方法接受一个参数(也就是被赋予的新值) ,会传入赋值时的 this 对象默认为 undefined。 文字有些晦涩难懂,看代码会更好理解些

代码语言:javascript
复制
Object.defineProperty(obj,'a'{
    //getter
    get(){
        console.log("你试图访问obj的a属性');
    }
    //setter
    set() {
        console.log("你试图改变obj的a属性');
    }
 })
console.log(obj.a);
obj.a = 10;

defineReactive函数

getter/setter需要变量转换

代码语言:javascript
复制
var temp;:
Object.defineProperty(obj,'a',[
    get(){
        console.log("你试图访问obj的a属性');return temp;
    }
    set(newValue) {
        console.log("你试图改变obj的a属性’,newValue);
        temp = newValue;
    }
})

但是使用defineReactive函数就不用设置临时变量了,用闭包即可。

代码语言:javascript
复制
function defineReactive(data,key,val) {
  Object.defineProperty(data,key,{
    enumerable: true,
    configurable:true,
    get() {
      console.log('访问obj的key属性')
    },
    set(newVal) {
      console.log('改变obj的key属性',)
      if(val === newVal) {
        return 
      }
      val = newVal
    }
  })
}

对象响应式处理

通过observe,将一个正常的object转换为每个层级 的属性都是响应式(可以被侦测的)的object

代码语言:javascript
复制
function Observer(data) {
    this.data = data;
    this.walk(data);
}
Observer.prototype = {
    walk: function(data) {
    var self = this;
    Object.keys(data).forEach(function(key) {
    self.convert(key, data[key]);
    });
},
convert: function(key, val) {
    this.defineReactive(this.data, key, val);
},
defineReactive: function(data, key, val) {
    var dep = new Dep();
    var childObj = observe(val);
    Object.defineProperty(data, key, {
    enumerable: true,
    configurable: true,
    get: function() {
    if (Dep.target) {
        dep.depend();
    }
        return val;
    },
    set: function(newVal) {
        if (val === newVal) {
        return;
    }
    val = newVal;
    childObj = observe(newVal);
    dep.notify();
    }
   });
 }
};
function observe(value, vm) {
    if (!value || typeof value !== 'object') {
    return;
}
    return new Observer(value);
};

如上代码所示,Observer会对数据进行劫持并且在每个数据属性中创建一个对应的Dep实例。Dep是Vue.js中的一个订阅者列表,用于收集依赖于该对象的所有Watcher对象,在数据变化时执行相应的update回调函数。当一个数据对象被监听后,Observer就会将其属性进行劫持,通过Object.defineProperty将属性改成getter/setter的形式,并当属性被读取时自动收集相应的Watcher对象,在属性变化时自动触发相应的更新逻辑。

Observer是Vue.js变化侦测系统中最为核心和重要的部分。通过Observer监听数据的变化并更新视图,才能实现Vue.js的双向数据绑定和响应式的数据更新机制。

数组的响应式处理

数组的响应式通过重写数组的方法来实现响应式(push,pop,shift,unshift,splice,sort,reverse)

至此数据响应式原理讲解完毕,如有错误,敬请指正。

本文参与 腾讯云自媒体分享计划,分享自作者个人站点/博客。
原始发表:2023-10-27,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 作者个人站点/博客 前往查看

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

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

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • Object.defineProperty()方法
  • getter和setter
  • defineReactive函数
  • 对象响应式处理
  • 数组的响应式处理
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档