2024.05.14
vue 响应式实现(2)
对象的拦截
- 创建一个
reactive.js作为编写的实现
const proxyObj = reactive({
a: 1,
b: 2,
c: {
aa: 11,
bb: 22
}
})
function reactive(target) { return new Proxy(target, { get() {}, set() {} }) }export { reactive }- 涉及到多种拦截的操作,如
get、set、add、delete等操作
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,}- 在拦截的时候根据对象的读写需要 触发依赖收集和更新
// 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' }- 根据访问方式完善代码
// 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) }- 通过调试发现一些没必要的依赖收集和更新,重新改造如下
// utils/utils.js
export function isObject(target) { return typeof target === 'object' && target !== null}export function hasChanged(oldV, newV) { return !Object.is(oldV, newV)}// 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) }- 做一些边界的判断
// 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 }