一、vue2的数据劫持
Object.defineProperty
1.第一个参数为要访问的对象名
2.第二个参数为要操作的属性,这个键名可以是还未在对象中设置的
3.第三个参数为一个对象,可以对这个属性进行设置
writable:是否允许修改这个值
configurable:是否允许删除这个值
enumerable:是否允许遍历这个值
代码示例
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Document</title>
</head>
<body>
<script>
let person = {
name:'wtx',
age:18
}
Object.defineProperty(person,'sex',{
// 定义sex属性对应的值
value:'girl',
// 是否允许修改这个值 默认为false,不允许修改 true为允许修改
writable:true,
// 是否允许删除这个值 默认为false,不允许删除 true为允许删除
configurable:false,
// 是否允许遍历这个值 默认为false,不允许遍历 true为允许遍历
enumerable:true
})
// 查看sex属性的值
// girl
console.log(person.sex);
// 修改sex属性的值
person.sex = 'boy'
// boy
console.log(person.sex);
// 删除sex属性
delete person.sex
delete person.name
// name删除成功,但是sex设置了不允许删除
// {age: 18, sex: 'boy'}
console.log(person);
// 遍历person对象的键名,设置了true,允许遍历
// ['age', 'sex']
console.log(Object.keys(person));
</script>
</body>
</html>
数据劫持实现vue的响应式原理;
get和set方法,当访问到设置的属性时,会调用get方法;当属性值被修改时,会调用set方法。
let obj = {
name:'华为',
price:'4999',
color:'black'
}
let val = '中国'
// 实现vue的响应式原理
Object.defineProperty(obj,'addr',{
// 当访问该属性时,会调用此函数
get() {
console.log('有人读取了这个属性');
return val
},
// 当属性值被修改时,会调用此函数
set(value) {
console.log('有人修改了这个值');
// 这是修改后的值
console.log(value);
val = value
}
})
// 4999
console.log(obj.price);
// 有人读取了这个属性 中国
console.log(obj.addr);
obj.made = '地球'
// 地球
console.log(obj.made);
// {name: '华为', price: '4999', color: 'black', made: '地球'}
console.log(obj);
二、vue3的数据劫持
proxy
let p = new Proxy(person,{get(target,key) {}})
第一个参数person为对象名 target为目标对象 key为属性名
代码示例
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>proxy</title>
</head>
<body>
<script>
let person = {
name:'wtx',
age:23
}
let p = new Proxy(person, {
get(target,key) {
console.log('有人访问了对象的属性'+key);
// 目标对象
console.log(target);
// 目标对象的属性
console.log(key);
// 目标对象的属性对应的属性值
return target[key]
}
})
// Proxy {name: 'wtx', age: 23}
console.log(p);
// 只要访问了对象的属性,就会触发get函数
// 有人访问了对象的属性 {name: 'wtx', age: 23} name wtx
console.log(p.name);
// 有人访问了对象的属性 {name: 'wtx', age: 23} age 23
console.log(p.age);
// 如果访问的属性不存在,那就返回undefined
// 有人访问了对象的属性 {name: 'wtx', age: 23} sex undefined
console.log(p.sex);
</script>
</body>
</html>
当要访问的属性不在对象中时,设置抛出异常。
// 处理访问的属性不在对象中的情况
let good = {
name:'小米手机',
price:3999,
color:'白色'
}
let p2 = new Proxy(good, {
get(target,key) {
// 如果访问的属性名在对象中 则返回属性值
if(key in target) {
console.log('有人访问了对象的属性'+key);
return target[key]
}else {
// 如果访问的属性名不在对象中,则抛出异常
throw new Error('属性不在对象中')
}
}
})
// 有人访问了对象的属性color 白色
console.log(p2.color);
// 抛出异常 属性不在对象中
console.log(p2.address);
proxy使用案例
去掉对象中某个属性的首尾空格
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>课前测</title>
</head>
<body>
<script>
// 匹配首位空格的正则
let reg = /^\s+|\s+$/g
let person = {
name:'wtx',
age:20
}
let p = new Proxy(person, {
// 获取
get(target,key) {
console.log('有人访问了这个属性');
return target[key]
},
// 修改
set(target,key,value) {
// 如果有空格,则去掉首尾空格
if(reg.test(value)==true) {
target[key] = value.trim()
}else {
console.log(222);
target[key] = value
}
}
})
p.name = ' cmh '
console.log(p.name);
</script>
</body>
</html>