vue原理与实现
Vue 的核心原理
Vue 是一个渐进式 JavaScript 框架,其核心原理主要包括响应式系统、虚拟 DOM、模板编译和组件化。以下是这些核心原理的详细解析。
响应式系统
Vue 的响应式系统基于 Object.defineProperty(Vue 2)或 Proxy(Vue 3)实现。当数据发生变化时,视图会自动更新。
-
Vue 2 的实现:通过
Object.defineProperty劫持对象的属性,为每个属性添加 getter 和 setter。当数据被访问或修改时,会触发依赖收集和派发更新。function defineReactive(obj, key, val) { Object.defineProperty(obj, key, { get() { console.log(`get ${key}: ${val}`); return val; }, set(newVal) { if (newVal !== val) { console.log(`set ${key}: ${newVal}`); val = newVal; } } }); } -
Vue 3 的实现:使用
Proxy代理整个对象,可以监听对象的所有操作(包括新增和删除属性)。function reactive(obj) { return new Proxy(obj, { get(target, key) { console.log(`get ${key}: ${target[key]}`); return target[key]; }, set(target, key, value) { if (target[key] !== value) { console.log(`set ${key}: ${value}`); target[key] = value; } return true; } }); }
虚拟 DOM
虚拟 DOM 是一个轻量级的 JavaScript 对象,用于描述真实 DOM 的结构。Vue 通过对比新旧虚拟 DOM 的差异,最小化 DOM 操作。
-
虚拟 DOM 的生成:模板编译后生成渲染函数,渲染函数执行后返回虚拟 DOM。
function createVNode(tag, props, children) { return { tag, props, children }; } -
Diff 算法:通过对比新旧虚拟 DOM 的节点,找出需要更新的部分。Vue 的 Diff 算法是双端比较算法,优化了对比效率。
模板编译
Vue 的模板编译将模板字符串转换为渲染函数。这个过程包括解析、优化和代码生成三个阶段。
- 解析:将模板字符串解析为抽象语法树(AST)。
- 优化:标记静态节点,避免不必要的重新渲染。
- 代码生成:将 AST 转换为渲染函数字符串。
function compile(template) { // 解析模板生成 AST const ast = parse(template); // 优化 AST optimize(ast); // 生成渲染函数 const code = generate(ast); return new Function(`with(this){return ${code}}`); }
组件化
Vue 的组件化允许将 UI 拆分为独立的、可复用的模块。每个组件都有自己的模板、逻辑和样式。
-
组件的定义:通过
Vue.component或单文件组件(SFC)定义组件。Vue.component('my-component', { template: '<div>My Component</div>', data() { return { message: 'Hello Vue' }; } }); -
组件的通信:父子组件通过
props和$emit通信,跨层级组件通过provide/inject或 Vuex 通信。
实现一个简易 Vue
以下是一个简易 Vue 的实现,包含响应式系统、模板编译和虚拟 DOM。
响应式系统实现
class Dep {
constructor() {
this.subscribers = new Set();
}
depend() {
if (activeEffect) {
this.subscribers.add(activeEffect);
}
}
notify() {
this.subscribers.forEach(effect => effect());
}
}
let activeEffect = null;
function watchEffect(effect) {
activeEffect = effect;
effect();
activeEffect = null;
}
function reactive(obj) {
Object.keys(obj).forEach(key => {
const dep = new Dep();
let value = obj[key];
Object.defineProperty(obj, key, {
get() {
dep.depend();
return value;
},
set(newValue) {
if (newValue !== value) {
value = newValue;
dep.notify();
}
}
});
});
return obj;
}
模板编译与渲染
function compile(template) {
// 简易模板编译:替换插值表达式
const renderStr = template.replace(/\{\{(.*?)\}\}/g, (match, p1) => {
return `_s(${p1.trim()})`;
});
return new Function('_s', `return \`${renderStr}\``);
}
function render(context, template) {
const renderFn = compile(template);
const html = renderFn(val => context[val]);
document.getElementById('app').innerHTML = html;
}
使用示例
const app = reactive({
message: 'Hello Vue'
});
watchEffect(() => {
render(app, '<div>{{ message }}</div>');
});
setTimeout(() => {
app.message = 'Hello World';
}, 1000);
总结
Vue 的核心原理包括响应式系统、虚拟 DOM、模板编译和组件化。通过实现一个简易 Vue,可以更深入地理解这些原理。实际开发中,Vue 还包含更多优化和功能,如指令、生命周期、路由和状态管理等。







