Skip to content

对象的拦截

  1. 创建一个 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 } 
  1. 涉及到多种拦截的操作,如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, 
} 
  1. 在拦截的时候根据对象的读写需要 触发依赖收集和更新
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'
    } 
  1. 根据访问方式完善代码
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) 
} 
  1. 通过调试发现一些没必要的依赖收集和更新,重新改造如下
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)  
}  
  1. 做一些边界的判断
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 }

最后更新时间: