vue源码简单剖析(1)---object如何实现变化侦测

        vue最大的特点之一就是数据驱动视图,也就是数据的变化,引起视图的变化。那么,第一步肯定要知道数据什么时候发生变化,这就叫做对数据的变化侦测

        想要知道数据什么时候发生变化,我们可以使用js的Object.defineProperty方法

let student = {
  'age': 11,
}

       我们可以直接通过student.age读取到学生的年龄是11,但是当学生年龄的值被修改了,我们如何才能主动知道值被修改了呢?

我们可以使用Object.defineProperty方法来写上述例子

let student = {};
let val = 11;
Object.defineProperty(student, 'age', {
  enumerable: true, // 是否可枚举
  configurable: true, // 是否可配置
  get(){
    console.log('age属性被读取了')
    return val
  },
  set(newVal){
    console.log('age属性被修改了')
    val = newVal
  }
})

        通过Object.defineProperty()方法给student一个age属性,并把这个属性的读和写用get()set()进行拦截,该属性进行读或写操作的时候就会分别触发get()set()。所以,student这个对象已经变成了可观测的

以下的vue源码,就是用来将对象的所有属性变成可观测的

  1. 先定义一个observer类,目的是将object转成可观测object
  2. value新增一个__ob__属性,作为标记,避免重复操作
  3. 判断数据类型,只有object类型才会调用walk方法,然后将每一个属性转换成getter/setter的形式来侦测变化
  4. 发现object子属性的值也是object形式的时候,通过new observer(val)递归子属性
// 源码位置:src/core/observer/index.js

/**
 * Observer类会通过递归的方式把一个对象的所有属性都转化成可观测对象
 */
export class Observer {
  constructor (value) {
    this.value = value
    // 给value新增一个__ob__属性,值为该value的Observer实例
    // 相当于为value打上标记,表示它已经被转化成响应式了,避免重复操作
    def(value,'__ob__',this)
    if (Array.isArray(value)) {
      // 当value为数组时的逻辑
      // ...
    } else {
      this.walk(value)
    }
  }

  walk (obj: Object) {
    const keys = Object.keys(obj)
    for (let i = 0; i < keys.length; i++) {
      defineReactive(obj, keys[i])
    }
  }
}
/**
 * 使一个对象转化成可观测对象
 * @param { Object } obj 对象
 * @param { String } key 对象的key
 * @param { Any } val 对象的某个key的值
 */
function defineReactive (obj,key,val) {
  // 如果只传了obj和key,那么val = obj[key]
  if (arguments.length === 2) {
    val = obj[key]
  }
  if(typeof val === 'object'){
      new Observer(val)
  }
  Object.defineProperty(obj, key, {
    enumerable: true,
    configurable: true,
    get(){
      console.log(`${key}属性被读取了`);
      return val;
    },
    set(newVal){
      if(val === newVal){
          return
      }
      console.log(`${key}属性被修改了`);
      val = newVal;
    }
  })
}

因此,只要将一个object传到observer中,那么这个object就会变成可观测的object。 

// 可观测的student 
let student = new Observer({
  'age': 11
})
  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值