# 3. 手写组合API ## 1) shallowReactive 与 reactive ```js const reactiveHandler = { get (target, key) { if (key==='_is_reactive') return true return Reflect.get(target, key) }, set (target, key, value) { const result = Reflect.set(target, key, value) console.log('数据已更新, 去更新界面') return result }, deleteProperty (target, key) { const result = Reflect.deleteProperty(target, key) console.log('数据已删除, 去更新界面') return result }, } /* 自定义shallowReactive */ function shallowReactive(obj) { return new Proxy(obj, reactiveHandler) } /* 自定义reactive */ function reactive (target) { if (target && typeof target==='object') { if (target instanceof Array) { // 数组 target.forEach((item, index) => { target[index] = reactive(item) }) } else { // 对象 Object.keys(target).forEach(key => { target[key] = reactive(target[key]) }) } const proxy = new Proxy(target, reactiveHandler) return proxy } return target } /* 测试自定义shallowReactive */ const proxy = shallowReactive({ a: { b: 3 } }) proxy.a = {b: 4} // 劫持到了 proxy.a.b = 5 // 没有劫持到 /* 测试自定义reactive */ const obj = { a: 'abc', b: [{x: 1}], c: {x: [11]}, } const proxy = reactive(obj) console.log(proxy) proxy.b[0].x += 1 proxy.c.x[0] += 1 ``` ## 2) shallowRef 与 ref ```js /* 自定义shallowRef */ function shallowRef(target) { const result = { _value: target, // 用来保存数据的内部属性 _is_ref: true, // 用来标识是ref对象 get value () { return this._value }, set value (val) { this._value = val console.log('set value 数据已更新, 去更新界面') } } return result } /* 自定义ref */ function ref(target) { if (target && typeof target==='object') { target = reactive(target) } const result = { _value: target, // 用来保存数据的内部属性 _is_ref: true, // 用来标识是ref对象 get value () { return this._value }, set value (val) { this._value = val console.log('set value 数据已更新, 去更新界面') } } return result } /* 测试自定义shallowRef */ const ref3 = shallowRef({ a: 'abc', }) ref3.value = 'xxx' ref3.value.a = 'yyy' /* 测试自定义ref */ const ref1 = ref(0) const ref2 = ref({ a: 'abc', b: [{x: 1}], c: {x: [11]}, }) ref1.value++ ref2.value.b[0].x++ console.log(ref1, ref2) ``` ## 3) shallowReadonly 与 readonly ```js const readonlyHandler = { get (target, key) { if (key==='_is_readonly') return true return Reflect.get(target, key) }, set () { console.warn('只读的, 不能修改') return true }, deleteProperty () { console.warn('只读的, 不能删除') return true }, } /* 自定义shallowReadonly */ function shallowReadonly(obj) { return new Proxy(obj, readonlyHandler) } /* 自定义readonly */ function readonly(target) { if (target && typeof target==='object') { if (target instanceof Array) { // 数组 target.forEach((item, index) => { target[index] = readonly(item) }) } else { // 对象 Object.keys(target).forEach(key => { target[key] = readonly(target[key]) }) } const proxy = new Proxy(target, readonlyHandler) return proxy } return target } /* 测试自定义readonly */ /* 测试自定义shallowReadonly */ const objReadOnly = readonly({ a: { b: 1 } }) const objReadOnly2 = shallowReadonly({ a: { b: 1 } }) objReadOnly.a = 1 objReadOnly.a.b = 2 objReadOnly2.a = 1 objReadOnly2.a.b = 2 ``` ## 4) isRef, isReactive 与 isReadonly ```js /* 判断是否是ref对象 */ function isRef(obj) { return obj && obj._is_ref } /* 判断是否是reactive对象 */ function isReactive(obj) { return obj && obj._is_reactive } /* 判断是否是readonly对象 */ function isReadonly(obj) { return obj && obj._is_readonly } /* 是否是reactive或readonly产生的代理对象 */ function isProxy (obj) { return isReactive(obj) || isReadonly(obj) } /* 测试判断函数 */ console.log(isReactive(reactive({}))) console.log(isRef(ref({}))) console.log(isReadonly(readonly({}))) console.log(isProxy(reactive({}))) console.log(isProxy(readonly({}))) ```