vue2通过 Object.defineProperty
vue3 通过 Proxy
核心代码Vue2
/**
* 观察某个对象的所有属性
* @param {Object} obj
*/
function observe(obj) {
for (const key in obj) {
// 循环为每一个对象属性添加get set 方法
let internalValue = obj[key];
let funcs = [];
Object.defineProperty(obj, key, {
get: function () {
// 依赖收集,记录:是哪个函数在用我
if (window.__func && !funcs.includes(window.__func)) {
funcs.push(window.__func);
}
return internalValue;
},
set: function (val) {
internalValue = val;
// 派发更新,运行:执行用我的函数
for (var i = 0; i < funcs.length; i++) {
funcs[i]();
}
},
});
}
}
function autorun(fn) {
window.__func = fn;
fn();
window.__func = null;
}
Vue3
/**
* 观察某个对象的所有属性
* @param {Object} obj
*/
function observe(obj) {
let funcs = {};
return new Proxy(obj, {
get: function (obj, key) {
// 依赖收集,记录:是哪个函数在用我
!funcs[key] && (funcs[key] = []);
if (window.__func && !funcs[key].includes(window.__func)) {
funcs[key].push(window.__func);
}
return obj[key];
},
set: function (obj, key, val) {
obj[key] = val;
// 派发更新,运行:执行用我的函数
for (var i = 0; i < funcs[key].length; i++) {
funcs[key][i]();
}
return obj[key];
},
});
}
function autorun(fn) {
window.__func = fn;
fn();
window.__func = null;
}
完整例子
<!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>
<link rel="stylesheet" href="./index.css" />
</head>
<body>
<div class="card">
<p id="firstName"></p>
<p id="lastName"></p>
<p id="age"></p>
</div>
<input type="text" oninput="user.name = this.value" />
<input type="date" onchange="user.birth = this.value" />
<script src="./euv.js"></script>
<script src="./index.js"></script>
</body>
</html>
var user = {
name: '克劳德',
birth: '1997-5-25',
};
observe(user); // 观察
// 显示姓氏
function showFirstName() {
document.querySelector('#firstName').textContent = '姓:' + user.name[0];
}
// 显示名字
function showLastName() {
document.querySelector('#lastName').textContent = '名:' + user.name.slice(1);
}
// 显示年龄
function showAge() {
var birthday = new Date(user.birth);
var today = new Date();
today.setHours(0), today.setMinutes(0), today.setMilliseconds(0);
thisYearBirthday = new Date(
today.getFullYear(),
birthday.getMonth(),
birthday.getDate()
);
var age = today.getFullYear() - birthday.getFullYear();
if (today.getTime() < thisYearBirthday.getTime()) {
age--;
}
document.querySelector('#age').textContent = '年龄:' + age;
}
autorun(showFirstName);
autorun(showLastName);
autorun(showAge);