VUE 2.x的响应式原理模型
程序员文章站
2022-03-13 08:27:48
123...
先把结果展示出来:(整个实现的源代码在下面,拿去试试)
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title>Document</title>
</head>
<body>
<script>
let ARRAY_METHODS = [
"push",
"pop",
"shift",
"unshift",
"reverse",
"sort",
"splice",
];
// 此方法仍然无法解决操作数组长度length属性的响应式问题 vue3的proxy 可以解决 替代方法:splice(0)
let array_methods = Object.create(Array.prototype);
ARRAY_METHODS.forEach((method) => {
array_methods[method] = function () {
console.log(`当前正在使用的是拦截后的方法:${method}`);
for (var i = 0; i < arguments.length; i++) {
reactify(arguments[i]);
}
let res = Array.prototype[method].apply(this, arguments);
return res;
};
});
// 劫持数据
function defineReactive(target, key, value, enumerable) {
Object.defineProperty(target, key, {
configurable: true,
enumerable: !!enumerable,
get() {
console.log(`读取${key}属性当前值为${value}`);
return value;
},
set(newVal) {
console.log(`设置${key}属性,改为:${newVal}`);
value = newVal;
},
});
}
// 数据响应式化处理
function reactify(o) {
let keys = Object.keys(o);
for (var i = 0; i < keys.length; i++) {
let key = keys[i];
let val = o[key];
if (Array.isArray(o[key])) {
val.__proto__ = array_methods; // 使用前文中的js劫持策略且只重写需要要改为响应式数组的原型方法
for (var j = 0; j < val.length; j++) {
reactify(val[j]);
}
} else {
defineReactive(o, key, val, true); // 数据劫持并响应式处理
}
}
}
// 数据源
let data = {
name: "zachary",
age: 18,
hobits: [{ title: "爬山" }, { title: "游泳" }, { title: "电子游戏" }],
};
reactify(data);
</script>
</body>
</html>
本文地址:https://blog.csdn.net/MrZachary_zlc/article/details/112860179