vue动态绑定实现原理
Vue 动态绑定的核心原理
Vue 的动态绑定主要通过数据劫持结合发布-订阅模式实现。核心是利用 Object.defineProperty(Vue 2.x)或 Proxy(Vue 3.x)监听数据变化,触发视图更新。
数据劫持的实现
在 Vue 2.x 中,通过 Object.defineProperty 劫持对象的属性:
function defineReactive(obj, key, val) {
Object.defineProperty(obj, key, {
get() {
console.log('get:', key);
return val;
},
set(newVal) {
if (newVal !== val) {
console.log('set:', key);
val = newVal;
// 触发更新
}
}
});
}
在 Vue 3.x 中改用 Proxy 实现更全面的拦截:
const proxy = new Proxy(obj, {
get(target, key) {
console.log('get:', key);
return target[key];
},
set(target, key, value) {
console.log('set:', key);
target[key] = value;
// 触发更新
return true;
}
});
依赖收集与派发更新
Vue 通过 Dep 类和 Watcher 类实现依赖管理:
class Dep {
constructor() {
this.subs = [];
}
addSub(sub) {
this.subs.push(sub);
}
notify() {
this.subs.forEach(sub => sub.update());
}
}
class Watcher {
update() {
// 执行更新操作
}
}
在数据劫持的 getter 中收集依赖,setter 中触发更新:
function defineReactive(obj, key, val) {
const dep = new Dep();
Object.defineProperty(obj, key, {
get() {
if (Dep.target) {
dep.addSub(Dep.target);
}
return val;
},
set(newVal) {
val = newVal;
dep.notify();
}
});
}
虚拟 DOM 与差异更新
Vue 通过虚拟 DOM 实现高效的视图更新:
function patch(oldVnode, vnode) {
// 比较新旧虚拟 DOM 差异
// 仅更新变化的部分
}
模板编译过程
Vue 将模板编译为渲染函数:
- 解析模板生成 AST
- 优化 AST(标记静态节点)
- 生成渲染函数代码
最终生成的渲染函数包含对数据的动态绑定:
function render() {
return _c('div', { attrs: { id: app } }, [
_c('p', [_v(_s(message))])
]);
}
响应式系统的运作流程
- 初始化时对数据进行响应式处理
- 编译模板生成渲染函数
- 首次执行渲染函数触发数据属性的
getter收集依赖 - 数据变化时触发
setter通知依赖更新 - 重新执行渲染函数生成新的虚拟 DOM
- 通过对比新旧虚拟 DOM 更新真实 DOM







