文章目录
一、Vue 核心架构设计
二、响应式系统源码解析
三、虚拟DOM与Diff算法实现 3.1 Diff算法流程图 3.2 核心Diff源码
四、模板编译全流程剖析
五、组件系统与生命周期
六、异步更新队列与性能优化
七、Vue 3 新特性源码对比
八、手写迷你Vue框架实战
总结
一、Vue 核心架构设计
1.1 整体架构流程图
模板/JSX
编译器
渲染函数
虚拟DOM树
Patch算法
真实DOM
数据响应系统
依赖收集
派发更新
1.2 模块职责划分
模块 源码文件 核心职责 响应式系统 src/core/observer 数据劫持/依赖管理 虚拟DOM src/core/vdom VNode创建/Diff/Patch 编译器 src/compiler 模板转渲染函数 组件系统 src/core/instance 组件实例生命周期管理
二、响应式系统源码解析
2.1 核心类关系图
Observer
+walk(data)
+defineReactive()
Dep
+subs: Watcher[]
+depend()
+notify()
Watcher
+get()
+update()
2.2 核心源码分析
2.2.1 数据劫持实现
export class Observer {
constructor ( value ) {
this . value = value
this . dep = new Dep ( )
def ( value, '__ob__' , this )
if ( Array. isArray ( value) ) {
this . observeArray ( value)
} else {
this . walk ( value)
}
}
walk ( obj ) {
const keys = Object. keys ( obj)
for ( let i = 0 ; i < keys. length; i++ ) {
defineReactive ( obj, keys[ i] )
}
}
}
function defineReactive ( obj, key ) {
const dep = new Dep ( )
let val = obj[ key]
Object. defineProperty ( obj, key, {
enumerable : true ,
configurable : true ,
get : function reactiveGetter ( ) {
if ( Dep. target) {
dep. depend ( )
}
return val
} ,
set : function reactiveSetter ( newVal ) {
if ( newVal === val) return
val = newVal
dep. notify ( )
}
} )
}
2.2.2 依赖收集过程
let uid = 0
export default class Dep {
static target = null
constructor ( ) {
this . id = uid++
this . subs = [ ]
}
depend ( ) {
if ( Dep. target) {
Dep. target. addDep ( this )
}
}
notify ( ) {
const subs = this . subs. slice ( )
for ( let i = 0 ; i < subs. length; i++ ) {
subs[ i] . update ( )
}
}
}
三、虚拟DOM与Diff算法实现
3.1 Diff算法流程图
Yes
No
Yes
No
Yes
No
新旧VNode对比
相同节点?
更新属性
替换节点
有子节点?
执行子节点Diff
流程结束
双指针遍历
找到可复用节点?
移动节点
新建节点
3.2 核心Diff源码
function updateChildren ( parentElm, oldCh, newCh ) {
let oldStartIdx = 0
let newStartIdx = 0
let oldEndIdx = oldCh. length - 1
let newEndIdx = newCh. length - 1
while ( oldStartIdx <= oldEndIdx && newStartIdx <= newEndIdx) {
if ( sameVnode ( oldStartVnode, newStartVnode) ) {
patchVnode ( ... )
oldStartIdx++
newStartIdx++
}
}
if ( oldStartIdx > oldEndIdx) {
addVnodes ( ... )
} else if ( newStartIdx > newEndIdx) {
removeVnodes ( ... )
}
}
四、模板编译全流程剖析
4.1 编译流程图
Template
AST
Render
解析器生成抽象语法树
优化器标记静态节点
代码生成器输出渲染函数
Template
AST
Render
4.2 编译阶段源码
export function compileToFunctions ( template ) {
const ast = parse ( template. trim ( ) )
optimize ( ast)
const code = generate ( ast)
return {
render : new Function ( code. render) ,
staticRenderFns : code. staticRenderFns. map ( fn => new Function ( fn) )
}
}
function render ( ) {
with ( this ) {
return _c ( 'div' , { attrs : { "id" : "app" } } , [
_c ( 'p' , [ _v ( _s ( message) ) ] ) ,
_c ( 'button' , { on : { "click" : handleClick} } , [ _v ( "Click" ) ] )
] )
}
}
五、组件系统与生命周期
5.1 组件初始化流程
initMixin
VueComponent
patch
合并选项
初始化生命周期
初始化事件
初始化渲染
创建$el
initMixin
VueComponent
patch
5.2 生命周期源码触发点
Vue . prototype. _init = function ( options ) {
initLifecycle ( vm)
initEvents ( vm)
initRender ( vm)
callHook ( vm, 'beforeCreate' )
initInjections ( vm)
initState ( vm)
initProvide ( vm)
callHook ( vm, 'created' )
if ( vm. $options. el) {
vm. $mount ( vm. $options. el)
}
}
六、异步更新队列与性能优化
6.1 更新队列流程图
数据变更
触发setter
将Watcher推入队列
nextTick后执行
执行Watcher.run
触发组件更新
6.2 核心实现代码
const queue = [ ]
let waiting = false
function flushSchedulerQueue ( ) {
queue. sort ( ( a, b ) => a. id - b. id)
for ( let i = 0 ; i < queue. length; i++ ) {
const watcher = queue[ i]
watcher. run ( )
}
resetSchedulerState ( )
}
export function queueWatcher ( watcher ) {
if ( ! queue. includes ( watcher) ) {
queue. push ( watcher)
}
if ( ! waiting) {
nextTick ( flushSchedulerQueue)
waiting = true
}
}
七、Vue 3 新特性源码对比
7.1 响应式系统升级
function reactive ( target ) {
return new Proxy ( target, {
get ( target, key, receiver) {
track ( target, key)
return Reflect. get ( ... arguments)
} ,
set ( target, key, value, receiver) {
Reflect. set ( ... arguments)
trigger ( target, key)
}
} )
}
7.2 编译优化对比
优化点 Vue 2 Vue 3 静态提升 无 标记静态节点 补丁标志 全量Diff 动态节点追踪 缓存事件 每次渲染重新创建 缓存事件处理函数
八、手写迷你Vue框架实战
8.1 核心实现代码
class MyVue {
constructor ( options ) {
this . $options = options
this . _data = options. data ( )
new Observer ( this . _data)
new Compiler ( options. el, this )
}
}
class Observer {
constructor ( data ) {
this . walk ( data)
}
walk ( data ) {
Object. keys ( data) . forEach ( key => {
defineReactive ( data, key, data[ key] )
} )
}
}
function defineReactive ( obj, key, val ) {
const dep = new Dep ( )
Object. defineProperty ( obj, key, {
get ( ) {
Dep. target && dep. addSub ( Dep. target)
return val
} ,
set ( newVal) {
val = newVal
dep. notify ( )
}
} )
}
总结
本文从Vue源码层面深入解析了响应式系统、虚拟DOM、模板编译等核心模块的实现原理。建议通过以下方式进一步学习:
使用Vue官方调试版本进行断点调试 参与Vue源码GitHub Issue讨论 对比不同版本实现差异