前言
大家好,我是程序员蒿里行。浅浅记录一下面试中的高频问题,请你谈一下Vue响应式原理。 必备前置知识,Vue2
官方文档中深入响应式原理及Vue3
官方文档中深入响应式系统。
什么是响应式
响应式本质是当数据变化的时候,会自动执行一些相关函数。
const apple = {
price: 2,
amount: 3
}
const totalPrice = () => apple.price * apple.amount;
假设去水果店买苹果,价格为两元,买三个,总价是六元。但是苹果价格调整后,我还得重新计算一遍总价,即调用totalPrice函数。针对我们前端场景,数据的变动,无法直接响应页面变化,还需要做额外操作,如获取DOM,将数据设置到对应节点上。为了减少程序员的开发负担,响应式也就诞生了。
下面的例子实现了极简的响应式,数据变动,会自动更新页面。
<div class="card">
<p id="firstName"></p>
<p id="lastName"></p>
<p id="age"></p>
</div>
<form>
<input oninput="user.name = this.value"/>
<input type="date" onchange="user.birthday = this.value">
</form>
var user = {
name: '张三',
birthday: '2000-1-1'
};
observe(user) // 观察对象
// 显示姓氏
function showFirstName () {
var firstName = document.getElementById('firstName');
firstName.textContent = '姓: ' + (user.name[0] || '');
}
// 显示名字
function showLastName () {
var lastName = document.getElementById('lastName');
lastName.textContent = '名: ' + user.name.slice(1);
}
// 显示年龄
function showAge () {
var age = document.getElementById('age');
var birth = new Date(user.birthday);
var now = new Date();
age.textContent = '年龄: ' + (now.getFullYear() - birth.getFullYear());
}
autoRun(showFirstName)
autoRun(showLastName)
autoRun(showAge)
/**
* 观察某个对象的所有属性
* @param {Object} obj
*/
function observe(obj) {
for(const key in obj) {
let internalValue = obj[key];
let funcs = new Set();
Object.defineProperty(obj, key, {
get() {
// 依赖收集,记录:是哪个函数在用我
if (window.__func && !funcs.has(window.__func)) {
funcs.add(window.__func);
}
return internalValue;
},
set(val) {
internalValue = val;
// 派发更新,运行:执行用我的函数
for (const func of funcs) {
func();
}
}
});