剖析vue3数据绑定原理 Proxy
//ES5
let obj = {}
Object.defineProperty(
obj,
'name', {
get() {
console.log('get');
return 'zxs'
},
set() {
console.log('set');
}
})
console.log(obj.name); //get zxs
obj.name = 'es'
let obj1 = {}
let newVal = ''
Object.defineProperty(obj1, 'name', {
get() {
console.log('读取了属性');
return newVal;
},
set(val) {
console.log("设置了属性");
newVal = val;
}
})
console.log(obj1.name);
obj1.name = 'es';
// ES6
let obj2 = {}
let p = new Proxy(obj2, {}) //参数1:要包装(拦截)的对象 //参数2: 拦截方法钩子函数,类似于上面的get,set
p.name = 'zxs';
console.log(obj2.name);
let arr = [7, 8, 9]
arr = new Proxy(arr, {
get(target, prop) {
console.log('target: ' + target + 'prop: ' + prop); //target: 7,8,9 prop: 1 //target是要包装的整个对象,prop是带的参数
return prop in target ? target[prop] : 'error'
}
})
console.log(arr[1]); //target: 7,8,9 prop: 1 8
console.log(arr[10]); //target: 7,8,9 prop: 10 error
let dict = {
'hello': '你好',
'world': '世界'
}
dict = new Proxy(dict, {
get(target, prop) {
return prop in target ? target[prop] : prop
}
})
console.log(dict['world']); //世界
console.log(dict['zxs']); //zxs
let arr1 = []
arr1 = new Proxy(arr1, {
set(target, prop, val) {
if (typeof val === 'number') {
console.log('target: ' + target + ' prop: ' + prop + ' val: ' + val);
target[prop] = val
return true
} else {
return false
}
}
})
arr1.push(5); //target: prop: 0 val: 5
arr1.push(6) //target: 5 prop: 1 val: 6
console.log(arr1[0], arr1[1], arr1.length); //target: 5,6 prop: length val: 2 //5 6 2
// has
let range = {
start: 1,
end: 5
}
range = new Proxy(range, {
has(target, prop) {
return prop >= target.start && prop <= target.end
}
})
console.log(2 in range); //true
console.log(6 in range); //false
let userinfo = {
username: 'zxs',
age: 100,
_pwd: '1234' //不想让外界访问到_pwd
}
userinfo = new Proxy(userinfo, {
ownKeys(target) {
return Object.keys(target).filter(key => !key.startsWith('_'));
}
})
for (let i in userinfo) {
console.log(i);
//username
//age
}
console.log(Object.keys(userinfo)); //['username', 'age']
let user = {
username: 'zxs',
age: 100,
_pwd: '12345' //不想让外界访问到_pwd,删除_pwd等等所有操作
}
user = new Proxy(user, {
get(target, prop) {
if (prop.startsWith('_')) {
// throw new Error('不可访问')
} else {
return target[prop]
}
},
set(target, prop, val) {
if (prop.startsWith('_')) {
throw new Error('不可访问')
} else {
target[prop] = val
return true
}
},
deleteProperty(target, prop) {
if (prop.startsWith('_')) {
throw new Error('不可删除')
} else {
delete target[prop]
return true
}
},
ownKeys(target) {
return Object.keys(target).filter(key => !key.startsWith('_'))
}
})
console.log(user); //['username', 'age']
console.log(user._pwd); //Error:不可访问
user.age = 18;
console.log(user.age = 18);
// try {
// user._pwd = 'xxx'
// } catch (e) {
// console.log(e.message); //不可访问
// }
// try {
// delete user._pwd
// } catch (e) {
// console.log(e.message); //不可删除
// }
for (let key in user) {
console.log(key);
//username
//age
}
// apply
//未知参数求和
let sum = (...args) => {
let num = 0;
args.forEach(item => {
num += item
})
return num;
}
sum = new Proxy(sum, {
apply(target, ctx, args) {
//ctx :目标对象的上下文对象(this)
return target(...args) * 2 //将求和函数结果*2
}
})
console.log(sum(1, 1, 1 ));//6
console.log(sum.call(null, 1, 1, 1)); //6
console.log(sum.apply(null,[1,1,1]));//6
// construct
let user1=class{
constructor(name){
this.name=name
}
}
user1 = new Proxy(user1, {
//拦截 new一个对象
construct(target, args,newTarget){
return new target(...args)
}
})
console.log(new user1('zxs')); //user1 {name: 'zxs'}

浙公网安备 33010602011771号