一、介绍
1. Vue.js响应式回顾
- Proxy对象实现属性监听
- 多层属性嵌套,在访问属性过程中处理下一级属性
- 默认监听动态添加的属性
- 默认监听属性的删除操作
- 默认监听数组索引和length属性
- 可以作为单独的模块使用
2. 核心函数
- reactive/ref/toRefs/computed
- effect
- track
- trigger
二、Proxy对象回顾
1. 在严格模式下,Proxy的函数得返回布尔类型的值,否则会报TypeError
Uncaught TypeError: ‘set’ on proxy: trap returned falsish for property ‘foo’
'use strict'
// 问题1: set和deleteProperty中需要返回布尔类型的值
// 严格模式下,如果返回false的话,会出现TypeError的异常
const target = {
foo: 'xxx',
bar: 'yyy'
}
// Reflect.getPrototypeOf()
// Object.getPrototypeOf()
const proxy = new Proxy(target, {
get (target, key, receiver) {
// return target[key]
return Reflect.get(target, key, receiver)
},
set (target, key, value, receiver) {
// target[key] = value
return Reflect.set(target, key, value, receiver) // 这里得写return
},
deleteProperty(target, key) {
// delete target[key]
return Reflect.deleteProperty(target, key) // 这里得写return
}
})
proxy.foo = 'zzz'
2. Proxy和Reflect中使用receiver
Proxy中receiver:Proxy或者继承Proxy的对象
React中receiver:如果target对象设置了getter,getter中的this指向receiver
const obj = {
get foo () {
console.log(this)
return this.bar
}
}
const proxy = new Proxy(obj, {
get(target, key, receiver) {
if (key === 'bar') {
return 'value - bar'
}
return Reflect.get(target, key, receiver) // 执行this.bar的时候,this指向代理对象,也就是获取target.bar
}
})
console.log(proxy.foo) // value - bar
如果return Reflect.get(target, key, receiver)
写成return Reflect.get(target, key)
的话,则响应式属性foo里面的this还是指向原本的对象obj,this.bar就是undefined,而传入了receiver之后,响应式属性里的this就指向新的响应式对象proxy,this.bar返回value - bar
。
三、reactive
- 接受一个参数,判断这个参数是否是对象
- 创建拦截器对象handler,设置get/set/deleteProperty
- 返回Proxy对象
自己实现reactive
function isObject(value) {
return value !== null && typeof value === 'object'
}
function convert(target) {
return isObject(target) ? reactive(target) : target
}
const hasOwnProperty = Object.prototype.hasOwnProperty
function hasOwn(target, key) {
return hasOwnProperty.call(target, key)
}