Vue2.X是如何利用Object.defineProperty()实现数据绑定的

Vue2.X是如何利用Object.defineProperty()实现数据绑定的

上一篇文章写到了Object.defineProperty的使用,这篇文章说一下Vue是如何利用这个方法实现数据绑定的。

首先把Vue中的核心方法defineReactive做一些简化

functiondefineReactive(obj,key,val,cb) {

vardep=newDep();

Object.defineProperty(obj,key, {

enumerable:true,

configurable:true,

get: ()=>{

/*....依赖收集等....*/

dep.depend()

returnval

       },

set:newVal=>{

val=newVal;

/*触发回调*/

dep.notify()

       }

   })

}

Vue通过defineReactive方法实现对需要观察的对象的每个属性进行监控。

dep对象就相当于一个调度中心的作用,如果有数据用到这个属性,它就会自动收集该属性到调度中心,如果某属性发生了改变,那就会通知调度中心来更新视图。

再看看dep方法和它的功能。相对比较简单:1、存储订阅者2、添加订阅者

function Dep () {

  // 所有的watcher 放进这里统一管理

  this.subs = []

}

Dep.target = null;

// 通知视图更新dom的 notify的方法

Dep.prototype.notify  = function () {

  // this.subs 存储 watcher

  this.subs.forEach(sub => {

   // sub 是某个Watcher 具体调用某个Watcher的update 方法

   sub.update()

  })

}

// 添加订阅者的方法

Dep.prototype.addSub = function (sub) {

  this.subs.push(sub)

}

订阅器主要也是了两个方法;1、触发一下属性的获取,顺便把自己加到调度中心去 2、update更新视图

// 具体的订阅器Watcher

// 传入一个vue 的示例, 监听的属性, 以及处理的回调函数

function Watcher (vm,prop,callback) {

  this.vm = vm;

  this.$prop = prop;

  this.value = this.get();

  this.callback = callback;

}

// 添加watcher 获得属性的get 方法,当有属性访问/设置 的时候,就产生订阅者 将这个订阅者放进调度中心

Watcher.prototype.get = function () {

  Dep.target = this;

  // 获得属性值

  const value = this.vm.$data[this.$prop];

  return value

}

// 添加watcher的更新视图的方法

Watcher.prototype.update = function () {

  // 当属性值有变化的时候,执行方法,更新试图

  const value = this.vm.$data[this.$prop];

  this.callback(this.value)

}

于是乎

当外界读取数据时会调用watcher,会触发getter把watcher添加到Dep依赖中。(也就是编译过程收集依赖)

当数据发生了变化,会触发setter,从而想Dep中的依赖(watcher)发送通知。(交互过程,调度中心去通知订阅器抓紧更新)。

Watcher 接收到通知后,会向外界发送通知,变化通知到外界可能触发试图更新,也有可能触发用户的某个回调函数等。(订阅器修改对应的值,页面参数随之相应,实现响应)

当然,这才只是单向绑定,双向绑定就是说视图更改数据,这个就比较简单,在编译过程中将标签绑定input方法,修改对应的数据即可。

有来有回,实现了双向绑定。

你可能感兴趣的:(Vue2.X是如何利用Object.defineProperty()实现数据绑定的)