Vue Object 的变化侦测实现代码

 更新时间:2020年04月15日 16:28:54   作者:charllote  
这篇文章主要介绍了Vue Object的变化侦测实现,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习学习吧

数据观察

Vue 中的对象变化侦测是通过Object.definePorperty实现的,但是Object.definePorperty的方式有缺陷,比如不能直接代理整个对象,每次都要循环遍历对象的所有属性;尤大大说之后会使用 ES6 中的Proxy 重写这个部分。这篇博客介绍的是 Object.definePorperty 实现的对象侦测。

我们来看下面这段代码,定义一个 defineReactive 函数,使用 Object.definePorperty 遍历对象对象属性的时候,设置 get 和 set;当对象属性被读取的时候触发 get,对象属性被设置的时候触发 set。这样就完成了对 data 的数据劫持,因为 Vue 的思想是响应式的,我们还需要收集这些变化。

function defineReactive(data,key,val){
  Object.definePorperty(data,key,{
    enumerable: true,
    configurable: true,
    get:function(){
      return val;
    }
    set :function (newVal){
      if(val === newVal){return}
      val = newVal;
    }
  })
}

依赖 收集

创建一个 Dep 类,在 get 中收集依赖,在 set 中新增依赖

class Dep{
  constructor(){
    this.arr = []
  }
  addSub(sub){
    this.arr.push(sub)
  }
   removeSub(sub){
    remove(this.arr,sub)
  }
  depend(){
    if(window.target){
      this.addSub(window.target)
    }
  }
  notify(){
    const arrs = this.arr.slice();
    for(let i = 0; i< arrs.lenth ;i ++){
      arrs[i].update();
    }
  }

}

function defineReactive(data,key,val){

  let dep = new Dep()
  Object.definePorperty(data,key,{
    enumerable: true,
    configurable: true,
    get:function(){
      dep.depend(); // 收集依赖
      return val;
    }
    set :function (newVal){
      if(val === newVal){return}
      val = newVal;
      dep.notify(); // 新增依赖
    }
  })
}

Observer 和 Watcher

我们发现 defineReactive 函数只能将某一个属性转换为 get/set 的形式,所以我们需要一个观察者 Observer 用来帮助递归的侦测所有的 key

class Observer{
  constructor(value){
    this.value = value
  }
  if(!Array.isArry(value)){
    this.walk(value)
  }
  walk(obj){
    const keys = Object.keys(obj)
    for(let i = 0; i < keys.length ;i++){
      defineReactive(data,keys[i],obj[keys[i])
    }
  }
}

当这些依赖收集完成之后,我们要通知谁呢?怎么样能让视图知道有变化更新?我们需要实现一个订阅者 Watcher,
每次触发 get 的时候都将 dep 指向自己,这样就可以收集到依赖;
每次 set 的时候都循环调用 Watcher 的 update 方法。

class Watcher{
  constructor(vm,exp,cb){
    this.vm = vm;
    this.cb = cb;
    this.exp = exp;
    this.value = this.get();
  }
  get(){
    Dep.target = this;  // 将当前订阅者指向自己
    var value = this.vm[exp];  // 触发getter,添加自己到属性订阅器中
    Dep.target = null;  // 添加完毕,重置
    return value;
  }
  update(){
    const oldVal = this.value;
    this.value = this.get();
    this.cb.call(this.vm,this.value,oldVal)
  }
}

当 Vue 实例挂载好之后,模板都会绑定一个 Watcher,谁的属性发生变化了就会通知响应的 Watcher,Watcher 再去通知编译器 Compile 进行视图更新

侦测没办法监听到对象上属性的新增和删除

Vue 通过Object.definePorperty将对象的 key 转化为 getter setter 的形式来进行侦测,但是无法追踪到属性的新增和删除,所以 Vue 中提供了 vm.get 来实现

到此这篇关于Vue Object 的变化侦测实现代码的文章就介绍到这了,更多相关Vue Object 变化侦测 内容请搜索脚本之家以前的文章或继续浏览下面的相关文章希望大家以后多多支持脚本之家!

相关文章

  • vue3+Element Plus v-model实现父子组件数据同步的案例代码

    vue3+Element Plus v-model实现父子组件数据同步的案例代码

    这篇文章主要介绍了vue3+Element Plus v-model实现父子组件数据同步,本文通过实例代码给大家介绍的非常详细,对大家的学习或工作具有一定的参考借鉴价值,需要的朋友可以参考下
    2024-01-01
  • Vue3.x如何设置浏览器动态Title方法

    Vue3.x如何设置浏览器动态Title方法

    这篇文章主要介绍了Vue3.x如何设置浏览器动态Title方法,具有很好的参考价值,希望对大家有所帮助,如有错误或未考虑完全的地方,望不吝赐教
    2024-03-03
  • Vue使用Echarts实现大屏可视化布局示例详细讲解

    Vue使用Echarts实现大屏可视化布局示例详细讲解

    这篇文章主要介绍了Vue使用Echarts实现大屏可视化布局示例,本文通过实例代码图文相结合给大家介绍的非常详细,对大家的学习或工作具有一定的参考借鉴价值,需要的朋友可以参考下
    2023-01-01
  • 如何使用 vue + d3 画一棵树

    如何使用 vue + d3 画一棵树

    这篇文章主要介绍了如何使用 vue + d3 画一棵树,本文通过文字说明加代码分析的形式给大家介绍的非常详细,具有一定的参考借鉴价值,需要的朋友可以参考下
    2018-12-12
  • Element Table的row-class-name无效与动态高亮显示选中行背景色

    Element Table的row-class-name无效与动态高亮显示选中行背景色

    这篇文章主要介绍了Element Table的row-class-name无效与动态高亮显示选中行背景色,本文详细的介绍了解决方案,小编觉得挺不错的,现在分享给大家,也给大家做个参考。一起跟随小编过来看看吧
    2018-11-11
  • Vue+Axios实现文件上传自定义进度条

    Vue+Axios实现文件上传自定义进度条

    这篇文章主要为大家详细介绍了Vue+Axios实现文件上传自定义进度条,文中示例代码介绍的非常详细,具有一定的参考价值,感兴趣的小伙伴们可以参考一下
    2022-08-08
  • 关于Echarts饼图图例太长的解决方案

    关于Echarts饼图图例太长的解决方案

    这篇文章主要介绍了关于Echarts饼图图例太长的解决方案,具有很好的参考价值,希望对大家有所帮助。如有错误或未考虑完全的地方,望不吝赐教
    2023-02-02
  • Vuejs第十篇之vuejs父子组件通信

    Vuejs第十篇之vuejs父子组件通信

    这篇文章主要介绍了Vuejs第十篇之vuejs父子组件通信的相关资料,本文介绍的非常详细,具有参考借鉴价值,需要的朋友可以参考下
    2016-09-09
  • vue3使用elementPlus进行table合并处理的示例详解

    vue3使用elementPlus进行table合并处理的示例详解

    虚拟数据中公司下有多个客户,公司一样的客户,公司列需要合并,客户如果一样也需要合并进行展示,所以本文给大家介绍了vue3使用elementPlus进行table合并处理的实例,文中通过代码示例介绍的非常详细,需要的朋友可以参考下
    2024-02-02
  • vue基于better-scroll仿京东分类列表

    vue基于better-scroll仿京东分类列表

    这篇文章主要为大家详细介绍了vue基于better-scroll仿京东分类列表,文中示例代码介绍的非常详细,具有一定的参考价值,感兴趣的小伙伴们可以参考一下
    2020-06-06

最新评论