闽公网安备 35020302035485号
2.ES6 的 Proxy
Object.defineProperty(obj, prop, option)入参用法:
var obj = {
name: 'sorryhc'
}
var rocordName = 'sorryhc';
Object.defineProperty(obj, 'name', {
enumerable: true,
configurable:true,
set: function(newVal) {
rocordName = newVal
console.log('set: ' + rocordName)
},
get: function() {
console.log('get: ' + rocordName)
return rocordName
}
})
obj.name = 'sorrycc' // set: sorrycc
console.log(obj.name) // get: sorrycc
对一个对象进行整体响应式监听:
// 监视对象
function observe(obj) {
// 遍历对象,使用 get/set 重新定义对象的每个属性值
Object.keys(obj).forEach(key => {
defineReactive(obj, key, obj[key])
})
}
function defineReactive(obj, k, v) {
// 递归子属性
if (typeof(v) === 'object') observe(v)
// 重定义 get/set
Object.defineProperty(obj, k, {
enumerable: true,
configurable: true,
get: function reactiveGetter() {
console.log('get: ' + v)
return v
},
// 重新设置值时,触发收集器的通知机制
set: function reactiveSetter(newV) {
console.log('set: ' + newV)
v = newV
},
})
}
// 堆代码 duidaima.com
let data = {a: 1}
// 监视对象
observe(data)
data.a // get: 1
data.a = 2 // set: 2
整体思路就是遇到子对象就递归,和深拷贝一样的读参顺序。3.如果修改数组的 length ( Object.defineProperty 不能监听数组的长度),以及数组的 push 等变异方法是无法触发 setter 的
const obj = new Proxy(target, handler)其中:
const handler = {
get: function(target, name){
return name in target ? target[name] : 'no prop!'
},
set: function(target, prop, value, receiver) {
target[prop] = value;
console.log('property set: ' + prop + ' = ' + value);
return true;
}
};
var user = new Proxy({}, handler)
user.name = 'sorryhc' // property set: name = sorryhc
console.log(user.name) // sorryhc
console.log(user.age) // no prop!
并且Proxy提供了更丰富的代理能力:getPrototypeOf / setPrototypeOf isExtensible / preventExtensions ownKeys / getOwnPropertyDescriptor defineProperty / deleteProperty get / set / has apply / construct感兴趣的可以查看 MDN[1] ,一一尝试一下,这里不再赘述
Object.defineProperty
window.obj = {
showModal: false
}
const [visible, setVisible] = useState(false);
useEffect(() => {
visible && Modal.show({
// ...
})
}, [visible])
Object.defineProperty(window.obj, 'showModal', {
enumerable: true,
configurable:true,
set: function(newVal) {
setVisible(newVal);
console.log('set: ' + newVal)
},
get: function() {
console.log('get: ' + visible)
return visible
}
})
window.obj.showModal = !window.obj.showModal // set: true
console.log(window.obj.showModal) // get: true
Proxy
const [visible, setVisible] = useState(false);
useEffect(() => {
visible && Modal.show({
// ...
})
}, [visible])
const handler = {
get: function(target, name){
return name in target ? target[name] : 'no prop!'
},
set: function(target, prop, value, receiver) {
target[prop] = value;
setVisible(value);
console.log('property set: ' + prop + ' = ' + value);
return true;
}
};
window.obj = new Proxy({showModal: false}, handler)
window.obj.showModal = !window.obj.showModal // property set: showModal = true
console.log(window.obj.showModal) // true
总结