const isObject = (val) => val !== null && typeof val === 'object'
const hasChanged = (val, oldVal) => val !== oldVal
const hasOwn = (val, key) => hasOwnProperty.call(val, key)
function createGetter(shallow = false, isReadonly = false) {
return function (target, key, receiver) {
const res = Reflect.get(...arguments)
console.log(`get key:${key}`)
if (!isReadonly) {
// track(target, 'get', key)
}
if (shallow) {
return res
}
if (isObject(res)) {
return isReadonly ? readonly(res) : reactive(res);// 继续响应化
}
return res
}
}
function createSetter() {
return function (target, key, value, receiver) {
const oldValue = target[key]
const hasKey = hasOwn(target, key)
const res = Reflect.set(...arguments)
if (!hasKey) {
console.log(`add key:${key},value:${value}`)
// track(target, 'add', key, value)
} else if (hasChanged(value, oldValue)) {
console.log(`set key:${key},value:${value}`)
// track(target, 'set', key, value, oldValue)
}
return res
}
}
const get = createGetter()
const set = createSetter()
const mutableHandlers = {
get,
set
}
function createReactiveObject(target, baseHandle) {
return new Proxy(target, baseHandle)
}
function reactive(target) {
return createReactiveObject(target, mutableHandlers)
}
const shallowGet = createGetter(true)
const shallowReactiveHandlers = Object.assign({}, mutableHandlers, {
get: shallowGet
})
function shallowReactive(target) {
return createReactiveObject(target, mutableHandlers)
}
const readonlyGet = createGetter(false, true);
const readonlyHandlers = {
get: readonlyGet,
set(target, key, value, receiver) {
console.warn(`Set operation on key "${String(key)}" failed: target is readonly.`, target);
return true
}
}
function readonly(target) {
return createReactiveObject(target, readonlyHandlers)
}
const shallowReadonlyGet = createGetter(true, true)
const shallowReadonlyHandlers = Object.assign({}, readonlyHandlers, {
get: shallowReadonlyGet
})
function shallowReadonly(target) {
return createReactiveObject(target, shallowReadonlyHandlers)
}
const targetObj = {
id: 1,
name: 'front-refined',
childObj: {
hobby: 'coding'
}
};
const proxyObject = shallowReadonly(targetObj)
proxyObject.childObj = []
console