vue3的响应式操作劫持
vue3响应式劫持操作主要用到了es6中的Proxy代理 与Reflect执行原有操作行为;
定义readonlyHandler处理对象 进行数据拦截
// 定义 readonlyHandler 处理函数
const readonlyHandler = {
get(target, prop) {
const result = Reflect.get(target, prop);
console.log('拦截到了读取数据', prop, result);
return result
},
set(target, prop, value) {
console.warn("只能读取数据,不能修改数据或者添加数据");
return true;
},
deleteProperty(target, prop) {
console.log('只能读取数据,不能删除数据');
return true;
}
}
手写shallowReadonly
// 定义一个shallowReadonly函数
function shallowReadonly(target) {
// 需要判读当前的数据是不是对象
if (target && typeof target === 'object') {
return new Proxy(target, readonlyHandler)
}
return target
}
手写readonly
// 定义一个readonly 函数
function readonly(target) {
// 需要判读当前的数据是不是对象
if (target && typeof target === 'object') {
// 判断target是不是数组
if (Array.isArray(target)) {
target.forEach((item, index) => {
target[index] = readonly(item);
})
}
// 判断target是否是对象
else {
// 遍历对象
Object.keys(target).forEach(key => {
target[key] = readonly(target[key]);
})
}
return new Proxy(target, readonlyHandler)
}
// 如果不是对象或者数组 自己返回
return target
}
检验
const proxyUser1 = shallowReadonly({
name: 'hhh',
schoolRecord: {
chinese: '88',
english: "59",
math: '99'
}
})
// shallowReadonly 可以读取数据
proxyUser1.name;
// shallowReadonly 不能修改数据
proxyUser1.name = '核酸';
// shallowReadonly 不能删除数据
delete proxyUser1.name;
console.log('########操作深层数据#########');
// shallowReadonly 可以读取深层的数据
proxyUser1.schoolRecord.math;
// shallowReadonly 可以修改深层的数据
proxyUser1.schoolRecord.math = '100';
// shallowReadonly 可以删除深层的数据
delete proxyUser1.schoolRecord.math
console.log('*********************################***********************');
const proxyUser2 = readonly({
name: 'zzz',
schoolRecord: {
chinese: '88',
english: "59",
math: '99'
}
})
// readonly 可以读取数据
proxyUser2.name;
// readonly 不能修改数据
proxyUser2.name = '核酸';
// readonly 不能删除数据
delete proxyUser2.name;
console.log('########操作深层数据#########');
// readonly 可以读取深层的数据
proxyUser2.schoolRecord.math;
// readonly 不可以修改深层的数据
proxyUser2.schoolRecord.math = '100';
// readonly 不可以删除深层的数据
delete proxyUser2.schoolRecord.math
测试完整代码
index.js
/*
* @Descripttion:
* @version:
* @Author: HHH
* @Date: 2021-02-22 17:12:08
* @LastEditors: HHH
* @LastEditTime: 2021-02-22 17:37:42
*/
// 定义 readonlyHandler 处理函数
const readonlyHandler = {
get(target, prop) {
const result = Reflect.get(target, prop);
console.log('拦截到了读取数据', prop, result);
return result
},
set(target, prop, value) {
console.warn("只能读取数据,不能修改数据或者添加数据");
return true;
},
deleteProperty(target, prop) {
console.log('只能读取数据,不能删除数据');
return true;
}
}
// 定义一个shallowReadonly函数
function shallowReadonly(target) {
// 需要判读当前的数据是不是对象
if (target && typeof target === 'object') {
return new Proxy(target, readonlyHandler)
}
return target
}
// 定义一个readonly 函数
function readonly(target) {
// 需要判读当前的数据是不是对象
if (target && typeof target === 'object') {
// 判断target是不是数组
if (Array.isArray(target)) {
target.forEach((item, index) => {
target[index] = readonly(item);
})
}
// 判断target是否是对象
else {
// 遍历对象
Object.keys(target).forEach(key => {
target[key] = readonly(target[key]);
})
}
return new Proxy(target, readonlyHandler)
}
// 如果不是对象或者数组 自己返回
return target
}
index.html
<!--
* @Descripttion:
* @version:
* @Author: HHH
* @Date: 2021-02-22 16:04:16
* @LastEditors: HHH
* @LastEditTime: 2021-02-22 17:42:13
-->
<!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>
<script src="./index.js"></script>
</head>
<body>
<script type="text/javascript">
const proxyUser1 = shallowReadonly({
name: 'hhh',
schoolRecord: {
chinese: '88',
english: "59",
math: '99'
}
})
// shallowReadonly 可以读取数据
proxyUser1.name;
// shallowReadonly 不能修改数据
proxyUser1.name = '核酸';
// shallowReadonly 不能删除数据
delete proxyUser1.name;
console.log('########操作深层数据#########');
// shallowReadonly 可以读取深层的数据
proxyUser1.schoolRecord.math;
// shallowReadonly 可以修改深层的数据
proxyUser1.schoolRecord.math = '100';
// shallowReadonly 可以删除深层的数据
delete proxyUser1.schoolRecord.math
console.log('*********************################***********************');
const proxyUser2 = readonly({
name: 'zzz',
schoolRecord: {
chinese: '88',
english: "59",
math: '99'
}
})
// readonly 可以读取数据
proxyUser2.name;
// readonly 不能修改数据
proxyUser2.name = '核酸';
// readonly 不能删除数据
delete proxyUser2.name;
console.log('########操作深层数据#########');
// readonly 可以读取深层的数据
proxyUser2.schoolRecord.math;
// readonly 不可以修改深层的数据
proxyUser2.schoolRecord.math = '100';
// readonly 不可以删除深层的数据
delete proxyUser2.schoolRecord.math
</script>
</body>
</html>