Appearance
对象的拦截
- 创建一个
reactive.js
作为编写的实现
js
const proxyObj = reactive({
a: 1,
b: 2,
c: {
aa: 11,
bb: 22
}
})
js
function reactive(target) {
return new Proxy(target, {
get() {},
set() {}
})
}
export { reactive }
- 涉及到多种拦截的操作,如
get、set、add、delete
等操作
js
import handle from './behover/index.js'
function reactive(target) {
// get(){},set(){}
return new Proxy(target, handle)
}
export { reactive }
// behover/index.js
function get(){}
function set(){}
function deleteProperty(){}
function ownKeys(){}
export {
get,sex,
}
- 在拦截的时候根据对象的读写需要 触发依赖收集和更新
js
// effect/track.js
/**
*
* @param traget 对象
* @param type 操作类型 是get还是has等。
* @param key
*/
export const track = (traget,type,key) => { }
// effect/trigger.js
export const trigger = (traget,type,key) => {}
// 所以创建操作类型的枚举
// 分为读写
// constant/enum.js
export const TrackOpTypes = {
GET: 'get',
HAS: 'has',
ITERATE: 'iterate'
}
export const TriggerOpTypes = {
SET: 'set',
ADD: 'add',
DELETE: 'delete'
}
- 根据访问方式完善代码
js
// behover/index
// proxyObj.a
function get(target,key) {
trigger(target, TrackOpTypes.GET,, key)
return Reflect.get(target,key)
}
// proxyObj.a = 2
function set(target,key,value){
trigger(target,TriggerOpTypes.SET,key)
return Reflect.set(target,key,value)
}
// delete proxyObj.a
function deletePropery(target,key) {
trigger(target,TriggerOpTypes.DELETE,key)
return Reflect.deleteProperty(target,key)
}
// 'a' in proxObj
function has(target,key){
track(target,TrackOpTypes,key)
return Reflect.has(target,key)
}
- 通过调试发现一些没必要的依赖收集和更新,重新改造如下
js
// utils/utils.js
export const isObject = (target) => {
return typeof target === 'object' && target !== null
}
export const hasChanged = (oldV, newV) => {
return !Object.is(oldV, newV)
}
js
// behover/index
// proxyObj.c.a
function get(target,key) {
trigger(target, TrackOpTypes.GET, key)
const result = Reflect.get(target,key)
if(isObject(result)) {
return reactive(result)
}
return result
}
// proxyObj.a = 2
function set(target,key,value){
// 是属性值的新增还是修改
const type = target.hasOwnProperty(key) ? TriggerOpTypes.SET : TriggerOpTypes.ADD
const oldValue = target[key]
const result = Reflect.set(target,key,value)
// 是否发生改变 决定是否派发更新
if(hasChanged(oldValue,value)){
trigger(target,TriggerOpTypes.SET,key)
}
return result
}
// delete proxyObj.a
function deletePropery(target,key) {
const result = Reflect.deleteProperty(target,key)
// 存在该属性
if (target.hasOwnProperty(key) && result) {
trigger(target, TriggerOpTypes.DELETE, key)
}
return result
}
// for (let key in proxyObj) {}
function ownKeys(target) {
track(target, TrackOpTypes.ITERATE)
return Reflect.ownKeys(target)
}
- 做一些边界的判断
js
// reactive.js
import handle from './behover/index.js'
import { isObject } from './utils/utils.js'
const proxyMap = new WeakMap()
function reactive(target) {
// 如果不是对象的话 直接返回
if(!isObject(target)) return target
return new Proxy(target, handle)
}
const proxy = new Proxy(target, handle)
// 如果已经代理过了,返回代理对象,
if(proxyMap.has(target)){
return proxyMap.get(target)
}
return proxy
}
export { reactive }