vue原理与实现
Vue 的核心原理
Vue 是一个渐进式 JavaScript 框架,其核心原理包括响应式系统、虚拟 DOM、模板编译和组件化设计。这些机制共同构成了 Vue 的高效开发模式。
响应式系统通过 Object.defineProperty 或 Proxy 实现数据劫持,当数据变化时自动触发视图更新。Vue 3 使用 Proxy 替代了 Vue 2 的 Object.defineProperty,解决了数组和对象属性监听不全的问题。
虚拟 DOM 是一个轻量级的 JavaScript 对象,描述真实 DOM 结构。通过对比新旧虚拟 DOM 的差异,最小化 DOM 操作,提升性能。
模板编译将模板字符串转换为渲染函数。Vue 2 使用正则表达式解析模板,Vue 3 改用基于有限状态机的解析器,效率更高。
实现简易 Vue 响应式系统
以下是一个基于 Proxy 的简易响应式实现:
function reactive(target) {
const handler = {
get(target, key, receiver) {
track(target, key);
return Reflect.get(target, key, receiver);
},
set(target, key, value, receiver) {
const oldValue = target[key];
const result = Reflect.set(target, key, value, receiver);
if (oldValue !== value) {
trigger(target, key);
}
return result;
}
};
return new Proxy(target, handler);
}
const targetMap = new WeakMap();
function track(target, key) {
let depsMap = targetMap.get(target);
if (!depsMap) {
targetMap.set(target, (depsMap = new Map()));
}
let dep = depsMap.get(key);
if (!dep) {
depsMap.set(key, (dep = new Set()));
}
dep.add(effect);
}
function trigger(target, key) {
const depsMap = targetMap.get(target);
if (!depsMap) return;
const dep = depsMap.get(key);
if (dep) {
dep.forEach(effect => effect());
}
}
虚拟 DOM 的简单实现
虚拟 DOM 的核心是 h 函数创建虚拟节点和 patch 函数对比更新:
function h(tag, props, children) {
return { tag, props, children };
}
function patch(oldNode, newNode) {
if (oldNode.tag === newNode.tag) {
const el = (newNode.el = oldNode.el);
// 更新属性
const oldProps = oldNode.props || {};
const newProps = newNode.props || {};
for (const key in newProps) {
if (newProps[key] !== oldProps[key]) {
el.setAttribute(key, newProps[key]);
}
}
for (const key in oldProps) {
if (!(key in newProps)) {
el.removeAttribute(key);
}
}
// 更新子节点
const oldChildren = oldNode.children || [];
const newChildren = newNode.children || [];
if (typeof newChildren === 'string') {
if (typeof oldChildren === 'string') {
if (newChildren !== oldChildren) {
el.textContent = newChildren;
}
} else {
el.textContent = newChildren;
}
} else {
if (typeof oldChildren === 'string') {
el.innerHTML = '';
newChildren.forEach(child => {
const childEl = createElement(child);
el.appendChild(childEl);
});
} else {
updateChildren(el, oldChildren, newChildren);
}
}
} else {
// 替换整个节点
const parent = oldNode.el.parentNode;
parent.removeChild(oldNode.el);
const newEl = createElement(newNode);
parent.appendChild(newEl);
}
}
组件系统实现原理
Vue 组件本质上是带有预定义选项的可复用 Vue 实例。组件的核心实现包括:
- 组件注册:通过
Vue.component全局注册或components选项局部注册 - 组件实例化:创建组件构造函数,继承自 Vue 基类
- 生命周期管理:从创建到销毁的各个阶段钩子函数
function createComponent(Ctor, data, context, children) {
const propsData = extractProps(data, Ctor.props);
const listeners = data.on || {};
const vnode = new VNode(
`vue-component-${Ctor.cid}${name ? `-${name}` : ''}`,
data, undefined, undefined, undefined, context,
{ Ctor, propsData, listeners, children }
);
return vnode;
}
模板编译过程
Vue 模板编译分为三个阶段:
- 解析:将模板字符串转换为 AST(抽象语法树)
- 优化:标记静态节点,减少 diff 过程中的比较
- 代码生成:将 AST 转换为可执行的渲染函数
function compile(template) {
const ast = parse(template);
optimize(ast);
const code = generate(ast);
return new Function(`with(this){return ${code}}`);
}
function parse(template) {
// 实现模板解析逻辑
// 返回 AST
}
function optimize(ast) {
// 标记静态节点
}
function generate(ast) {
// 生成渲染函数代码字符串
}
响应式系统的依赖收集
依赖收集是响应式系统的核心,通过 Dep 和 Watcher 实现:
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;
}
以上实现展示了 Vue 核心功能的简化版本,实际 Vue 源码更加复杂,包含更多边界情况处理和性能优化。理解这些基本原理有助于更好地使用 Vue 和解决开发中的问题。







