在Vue2中我们都知道使用的是 Object.defineProperty,那么我们看看在Vue2中如何通过这个方法来实现页面的实时更新呢
本人能力有限,没办法写出render(),只能用最笨的方法来模拟页面,如果有知道的小伙伴还希望私信互相学习。
废话不多说上代码!
<body>
<!-- template -->
<button id="age">修改年龄</button>
<button id="name">修改姓名</button>
<button id="count">修改count</button>
<h1 id="info"></h1>
<!-- 逻辑部分 -->
<script>
// 获取所有dom
const changeAge = document.getElementById("age");
const changeName = document.getElementById("name");
const changeCount = document.getElementById("count");
// 展示数据
const info = document.getElementById("info");
const state = {
count: 0,
person: {
name: ["TOM"],
age: 12,
},
};
function observe(obj) {
// 判断数据类型
if (typeof obj !== "object" || obj === null) return;
// 遍历需要监听对象的属性名
Object.keys(obj).forEach((key) => {
let currentValue = obj[key]; //获取当前遍历的属性值
observe(currentValue); // 递归监听属性值
Object.defineProperty(obj, key, {
get() {
return currentValue;
},
set(newValue) {
// 新旧值对比
if (currentValue !== newValue) {
currentValue = newValue;
// 更新视图
updateView();
}
},
});
});
}
observe(state);
// 更新视图
function updateView() {
info.innerHTML = `姓名:${state.person.name};年龄:${state.person.age};count:${state.count},address:${state.adress}`;
}
changeAge.onclick = () => {
state.adress = "lalalalal";
state.person.age++;
};
changeName.onclick = () => {
// 新的数组元素不会被响应式监听到
state.person.name.push(Math.random().toFixed(1) + "111");
state.person.name[0] = "abc";
state.person.name[1] = "ccc";
};
changeCount.onclick = () => {
state.count++;
state.adress = Math.random().toFixed(1) + "111";
};
</script>
</body>
那么Vue3采用了ES6新增的Proxy对象来实现响应式,我们看看区别到底在哪
<body>
<!-- template -->
<button id="age">修改年龄</button>
<button id="name">修改姓名</button>
<button id="count">修改count</button>
<h1 id="info"></h1>
<script>
// 获取所有dom
const changeAge = document.getElementById("age");
const changeName = document.getElementById("name");
const changeCount = document.getElementById("count");
const info = document.getElementById("info");
const state = reactive({
count: 0,
person: {
name: ["TOM"],
age: 12,
},
});
// reactive
function reactive(obj) {
return new Proxy(obj, {
// 如果有人访问了对象,触发get
get(target, key) {
if (typeof target[key] === "object" && target[key] !== null) {
return reactive(target[key]);
}
return target[key];
},
// 如果有人修改了对象,触发set
set(target, key, value) {
target[key] = value;
// 触发视图更新
updateView();
return true;
},
});
}
// 更新视图
function updateView() {
info.innerHTML = `姓名:${state.person.name};年龄:${state.person.age};count:${state.count}`;
}
changeAge.onclick = () => {
state.person.age++;
};
changeName.onclick = () => {
state.person.name.push(Math.random().toFixed(1) + "111");
};
changeCount.onclick = () => {
state.count++;
};
</script>
</body>