Vue源码解析:数据双向绑定(响应式)原理,真香

}

console.log(${key}属性被修改了);

val = newVal;

}

})

}

我们声明一个Observer类,用于将对象的所有属性都转变为可侦测,并且,我们要给每一个可侦测的对象添加一个__ob__属性,值为value的Observer的实例,这就相当于给每一个value设置了标识,表示这个value是响应式的了。那么当value是一个对象的时候,我们拿到他的所有的key,循环遍历调用Object.defineProperty()的方法,调用get/set方法来侦测,当发现传入的是一个Object的时候,通过递归的方式,再次通过Observer类去实例这个Object。这样我们就实现了对象的侦测。

2、实现数组的侦测(可观察)

上面我们讲了对象的侦测,现在来聊聊数组的侦测。

数组的可观测与对象的可观测有所不同,因为数组不能用Object.defineProperty()去观测。那么数组如何做到可观测呢,其实大同小异,数组是通过拦截器来做到的,那么这个拦截器是何方神圣?

我们知道,JavaScript中操作数组的原生方法,其实就是那么几个,push/pop/shift/unshift/splice/sort/reverse。这些方法都是通过Array.prototype来访问,那么我们如果在Array.prototype上重新定义一个方法,去实现原生的方法,如newPush去实现与push同样的作用,是不是很完美。既没有修改原生方法,又可以在调用原生方法之前做了相应的操作。

let arr = [1,2,3]

// arr.push(4) 原生方法调用

Array.prototype.newPush = function(val){

console.log(‘arr被修改了’)

this.push(val)

}

arr.newPush(4)

所以,数组的拦截器就是在数组实例和Array.prototype之间重写了操作数组的方法。这样在调用处理的方法的时候,就是调用的重写之后的方法,而不是原生方法。来看拦截器的实现:

// 源码位置:/src/core/observer/array.js

const arrayProto = Array.prototype

export const arrayMethods = Object.create(arrayProto)

const methodsToPatch = [

‘push’,

‘pop’,

‘shift’,

‘unshift’,

‘splice’,

‘sort’,

‘reverse’

]

methodsToPatch.forEach(function (method) {

const original = arrayProto[method]

Object.defineProperty(arrayMethods, method, {

enumerable: false,

configurable: true,

writable: true,

value:function mutator(…args){

const result = original.apply(this, args)

return result

}

})

})

这就是拦截器的实现,当调用数组的方法时,实际调用的是mutator函数,所以,我们可以在这个函数中做一些操作。但是这么做还不够,只有将拦截器挂载在数组实例和Array.prototype之间才能生效,也就是将数据的__proto__属性设置为拦截器arrayMethods即可

augment(value, arrayMethods, arrayKeys)

// 源码位置:/src/core/observer/index.js

export class Observer {

constructor (value) {

this.value = value

if (Array.isArray(value)) {

const augment = hasProto

? protoAugment
copyAugment

augment(value, arrayMethods, arrayKeys)

} else {

this.walk(value)

}

}

}

// 能力检测:判断__proto__是否可用ÿ

  • 7
    点赞
  • 13
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值