vue双向数据绑定原理2-前置知识点defineProperty

1.Object.defineProperty

  基本使用方法:第一个参数是被拦截的对象,第二个参数是对象的具体属性,第三个是一个对象,里面有对该属性的具体配置。

const obj = {
  name: 'cloudgaps',
  age: '18',
  info: {
    a:'1',
    b:'2'
  }
}

Object.defineProperty(obj,'name',{
  enumerable:true, //当前属性允许被循环 枚举
  configurable:true,  //当前属性允许被配置 删除
  get(){},  //取值拦截 getter
  set(newVal){}   //赋值拦截 setter
})

当访问obj.name时,会先被defineProperty中的get方法拦截,

当为obj.name赋值时,会被defineProperty中的set方法拦截,set方法中可以拿到你赋的最新值。

 上文说到,当vue监听到最新赋值后应该通知订阅者,而监听的时候就是在set内,此时我们就应该在set内调用通知订阅者的notify去通知订阅者。

2.vue中其实是在vue的实例对象中定义了一个数据劫持的方法,该方法会拿到data中的数据,为所有数据添加get和set方法,当vue中的数据有了变化时,每个数据对应的set内就会拿到最新的值并通过发布订阅模式去通知订阅者

const obj = {
  name: 'cloudgaps',
  age: '18',
  info: {
    a:'1',
    b:'2'
  }
}

// vue构造函数中定义的数据劫持的方法
function Observe() { 
  // 递归的终止条件
  if(!obj || typeof obj !== 'object') return false
  //Object.keys遍历对象中的每个key,并返回所有key组成的一个数组
Object.keys(obj).forEach(key => {
  // 当前循环的属性所对应的值
  let value = obj[key]
  // 进行递归
  Observe(value)
  Object.defineProperty(obj,key,{
    enumerable:true,
    configurable:true,
    get(){
      // 当数据被访问,则return出当前的值出去给访问者拿到
      return value
    },
    set(newValue){
      // 如果值被重新设置,则将value设置为最新的value
      // 那么再访问拿到该值时就时最新的value了
      value = newValue
      //当重新赋值后再调用observe为数据增加getter和setter
      Observe(value)
    }
  })
})
}

注:只写出了data中是对象的情况,如果数据是数组,则另作讨论,但原理是一致的。

 vue中实例对象直接访问到数据也是通过这一原理,将

// 假设vm是vue单页面的实例对象
const vm = new Vue({
  // 传入了obj数据
})

class Vue {
  constructor(options){
    this.$data = options.data
  }
  // 此时我们拿到页面的数据要通过vm.$data才能拿到 十分不方便
  // 于是我们通过defineProperty代理属性将数据代理到vm上
   Object.keys(this.$data).forEach(key => {
    //  this指向的就是vm实例对象
    Object.defineProperty(this,key, {
          enumerable:true,
          configurable:true,
          get(){
            return this.$data[key]
          },
          set(newValue){
            this.$data[key] = newValue
          }
}

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值