技术文档中心
首页
React
Vue
TypeScript
Kotlin
React Native
Electron
Android
首页
React
Vue
TypeScript
Kotlin
React Native
Electron
Android
  • Vue2 基础

    • Vue 学习指南
    • Vue2 快速入门
    • Vue2 模板语法
    • Vue2 组件基础
    • Vue2 计算属性与侦听器
    • Vue2 生命周期
  • Vue2 进阶

    • Vue2 组件通信
    • Vue2 插槽详解
    • Vue2 混入与自定义指令
    • Vue2 过渡与动画
    • Vuex 状态管理
  • Vue2 高级

    • Vue2 性能优化
    • Vue2 服务端渲染(SSR)
    • Vue2 源码解析
  • Vue3 基础

    • Vue3 快速入门
    • Vue3 Composition API
    • Vue3 响应式系统
    • Vue3 组件基础
    • Vue3 生命周期
  • Vue3 进阶

    • Vue3 组合式函数
    • Vue3 组件通信
    • Vue3 Teleport 与 Suspense
    • Pinia 状态管理
    • Vue Router 4
  • Vue3 高级

    • Vue3 TypeScript
    • Vue3 性能优化
    • Vue3 测试
    • Vue3 SSR
    • Vue3 源码解析
  • 实战项目

    • Vue2 实战项目
    • Vue3 实战项目
    • Vue2 迁移 Vue3

Vue3 源码解析

响应式系统

Proxy 实现

function reactive(target) {
  return new Proxy(target, {
    get(target, key, receiver) {
      track(target, key)
      return Reflect.get(target, key, receiver)
    },
    set(target, key, value, receiver) {
      const result = Reflect.set(target, key, value, receiver)
      trigger(target, key)
      return result
    }
  })
}

依赖收集

let activeEffect = null

function track(target, key) {
  if (!activeEffect) return
  
  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(activeEffect)
}

触发更新

function trigger(target, key) {
  const depsMap = targetMap.get(target)
  if (!depsMap) return
  
  const dep = depsMap.get(key)
  if (dep) {
    dep.forEach(effect => effect())
  }
}

effect 函数

function effect(fn) {
  const effectFn = () => {
    activeEffect = effectFn
    fn()
    activeEffect = null
  }
  
  effectFn()
  return effectFn
}

编译器

模板编译流程

模板字符串
  ↓
parse (解析)
  ↓
AST (抽象语法树)
  ↓
transform (转换)
  ↓
优化后的 AST
  ↓
generate (生成)
  ↓
render 函数

简化的 parse

function parse(template) {
  const ast = {
    type: 'Root',
    children: []
  }
  
  // 解析模板生成 AST
  // ...
  
  return ast
}

简化的 transform

function transform(ast) {
  // 静态提升
  // PatchFlag 标记
  // ...
}

简化的 generate

function generate(ast) {
  return `
    function render() {
      return h('div', null, 'Hello')
    }
  `
}

虚拟 DOM

VNode 结构

const vnode = {
  type: 'div',
  props: {
    id: 'app',
    class: 'container'
  },
  children: [
    {
      type: 'p',
      children: 'Hello'
    }
  ]
}

h 函数

function h(type, props, children) {
  return {
    type,
    props,
    children
  }
}

Diff 算法

function patch(n1, n2, container) {
  if (n1 && n1.type !== n2.type) {
    unmount(n1)
    n1 = null
  }
  
  const { type } = n2
  
  if (typeof type === 'string') {
    if (!n1) {
      mountElement(n2, container)
    } else {
      patchElement(n1, n2)
    }
  }
}

快速 Diff

Vue3 使用最长递增子序列算法优化 Diff:

function patchKeyedChildren(c1, c2, container) {
  let i = 0
  const l2 = c2.length
  let e1 = c1.length - 1
  let e2 = l2 - 1
  
  // 1. 从头部开始比较
  while (i <= e1 && i <= e2) {
    const n1 = c1[i]
    const n2 = c2[i]
    if (isSameVNodeType(n1, n2)) {
      patch(n1, n2, container)
    } else {
      break
    }
    i++
  }
  
  // 2. 从尾部开始比较
  while (i <= e1 && i <= e2) {
    const n1 = c1[e1]
    const n2 = c2[e2]
    if (isSameVNodeType(n1, n2)) {
      patch(n1, n2, container)
    } else {
      break
    }
    e1--
    e2--
  }
  
  // 3. 处理剩余节点
  // ...
}

组件化

组件实例

function createComponentInstance(vnode) {
  const instance = {
    vnode,
    type: vnode.type,
    props: {},
    slots: {},
    setupState: {},
    ctx: {},
    isMounted: false
  }
  
  return instance
}

组件挂载

function mountComponent(vnode, container) {
  const instance = createComponentInstance(vnode)
  
  setupComponent(instance)
  setupRenderEffect(instance, container)
}
最近更新: 2026/1/27 15:51
Contributors: hailong
Prev
Vue3 SSR