vue3详解

Vue 3 深度解析:从响应式原理到编译优化的完整指南

第一章:Vue 3 架构设计与核心思想

1.1 Vue 3 设计哲学与技术突破

Vue 3 是一次彻底的重构,其核心设计理念围绕 "渐进式""组合式""性能优先" 展开。让我们从架构层面深入理解 Vue 3 的设计选择。

架构演进:从 Monolithic 到 Module-based

// Vue 2 的架构(Monolithic)
class Vue2 {
  constructor(options) {
    // 所有功能耦合在一起
    this.initData(options.data)
    this.initComputed(options.computed)
    this.initWatch(options.watch)
    this.initMethods(options.methods)
    // 渲染逻辑、响应式逻辑、生命周期逻辑高度耦合
  }
}

// Vue 3 的架构(模块化)
import { reactive, computed, watchEffect } from '@vue/reactivity'
import { createRenderer } from '@vue/runtime-core'
import { compile } from '@vue/compiler-dom'

// 响应式系统:独立的包
const state = reactive({ count: 0 })

// 运行时核心:独立的包
const renderer = createRenderer(/* renderer options */)

// 编译器:独立的包
const { code } = compile('<div>{{ count }}</div>')

Composition API 的哲学转变

Composition API 不仅仅是 API 的改变,更是思维模式的转变:

// Options API (Vue 2 风格)
export default {
  data() {
    return { count: 0, message: 'Hello' }
  },
  computed: {
    doubleCount() {
      return this.count * 2
    }
  },
  methods: {
    increment() {
      this.count++
    }
  },
  watch: {
    count(newVal) {
      console.log('count changed:', newVal)
    }
  }
}

// Composition API (Vue 3 风格)
import { ref, computed, watch, onMounted } from 'vue'

export default {
  setup() {
    // 逻辑关注点分离:计数器逻辑
    const count = ref(0)
    const doubleCount = computed(() => count.value * 2)
    const increment = () => count.value++
    
    watch(count, (newVal) => {
      console.log('count changed:', newVal)
    })
    
    // 逻辑关注点分离:消息逻辑
    const message = ref('Hello')
    const updateMessage = (newMsg) => {
      message.value = newMsg
    }
    
    // 生命周期
    onMounted(() => {
      console.log('Component mounted')
    })
    
    // 按逻辑组织代码,而不是按选项类型
    return {
      // 计数器相关
      count,
      doubleCount,
      increment,
      
      // 消息相关
      message,
      updateMessage
    }
  }
}

1.2 响应式系统架构

Vue 3 的响应式系统是完全重写的,基于 ES6 Proxy 实现,其架构设计精妙且高效。

响应式系统核心架构图

响应式系统架构:
┌─────────────────────────────────────────────────────┐
│                 响应式数据 (reactive/ref)             │
├─────────────────────────────────────────────────────┤
│  Proxy/Getter          │  Dep (依赖收集)              │
│  (数据访问拦截)        │  (收集effect)                 │
├─────────────────────────────────────────────────────┤
│  Trigger (触发更新)    │  Effect (副作用)             │
│  (通知所有effect)      │  (需要重新执行的函数)          │
├─────────────────────────────────────────────────────┤
│  Scheduler (调度器)    │  Component (组件)            │
│  (控制更新时机)        │  (UI更新)                    │
└─────────────────────────────────────────────────────┘

响应式系统的分层设计

// 第一层:原始响应式API
import { reactive, ref, computed, watch } from 'vue'

// 第二层:响应式核心(@vue/reactivity包)
import {
  effect,          // 副作用函数
  track,           // 依赖收集
  trigger,         // 触发更新
  ReactiveEffect,  // 响应式effect类
  reactiveMap      // 响应式对象缓存
} from '@vue/reactivity'

// 第三层:代理处理器
const baseHandlers = {
  get(target, key, receiver) {
    track(target, TrackOpTypes.GET, 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, TriggerOpTypes.SET, key, value, oldValue)
    }
    return result
  },
  // ... 其他操作符
}

// 第四层:数据类型处理
const collectionHandlers = {
  // Map, Set, WeakMap, WeakSet 的特殊处理
  get(target, key, receiver) {
    if (key === 'size') {
      track(target, TrackOpTypes.ITERATE, ITERATE_KEY)
      return Reflect.get(target, key, receiver)
    }
    return mutableInstrumentations[key]
  }
}

第二章:响应式系统深度解析

2.1 Proxy-based 响应式原理

Proxy 拦截器的完整实现

// 响应式对象的创建过程
function reactive(target: object) {
  // 1. 如果已经是响应式对象,直接返回
  if (target && (target as any).__v_isReactive) {
    return target
  }
  
  // 2. 如果target是readonly响应式对象,直接返回
  if (target && (target as any).__v_isReadonly) {
    return target
  }
  
  // 3. 从缓存中查找
  const existingProxy = reactiveMap.get(target)
  if (existingProxy) {
    return existingProxy
  }
  
  // 4. 创建代理
  const proxy = new Proxy(
    target,
    baseHandlers
  )
  
  // 5. 设置标志并缓存
  ;(proxy as any).__v_isReactive = true
  reactiveMap.set(target, proxy)
  
  return proxy
}

// 基础处理器实现(简化版)
const baseHandlers: ProxyHandler<any> = {
  get(target: Target, key: string | symbol, receiver: object) {
    // 1. 特殊属性访问(__v_isReactive, __v_raw等)
    if (key === ReactiveFlags.IS_REACTIVE) {
      return true
    }
    if (key === ReactiveFlags.RAW) {
      return target
    }
    
    // 2. 依赖收集
    track(target, TrackOpTypes.GET, key)
    
    // 3. 获取值
    const res = Reflect.get(target, key, receiver)
    
    // 4. 如果是对象,递归响应化
    if (isObject(res)) {
      return reactive(res)
    }
    
    return res
  },
  
  set(target: Target, key: string | symbol, value: any, receiver: object): boolean {
    // 1. 获取旧值
    const oldValue = target[key]
    
    // 2. 检查是否为新增属性
    const hadKey = hasOwn(target, key)
    
    // 3. 执行设置
    const result = Reflect.set(target, key, value, receiver)
    
    // 4. 触发更新(避免触发原型链上的setter)
    if (target === toRaw(receiver)) {
      if (!hadKey) {
        // 新增属性
        trigger(target, TriggerOpTypes.ADD, key, value)
      } else if (hasChanged(value, oldValue)) {
        // 修改属性
        trigger(target, TriggerOpTypes.SET, key, value, oldValue)
      }
    }
    
    return result
  },
  
  deleteProperty(target: Target, key: string | symbol): boolean {
    // 1. 检查属性是否存在
    const hadKey = hasOwn(target, key)
    const oldValue = target[key]
    
    // 2. 执行删除
    const result = Reflect.deleteProperty(target, key)
    
    // 3. 触发更新
    if (result && hadKey) {
      trigger(target, TriggerOpTypes.DELETE, key, undefined, oldValue)
    }
    
    return result
  },
  
  has(target: Target, key: string | symbol): boolean {
    const result = Reflect.has(target, key)
    
    // 依赖收集
    if (!isSymbol(key) || !builtInSymbols.has(key)) {
      track(target, TrackOpTypes.HAS, key)
    }
    
    return result
  },
  
  ownKeys(target: Target): Array<string | symbol> {
    // 依赖收集
    track(target, TrackOpTypes.ITERATE, isArray(target) ? 'length' : ITERATE_KEY)
    
    return Reflect.ownKeys(target)
  }
}

// 特殊集合类型的处理器
const collectionHandlers: ProxyHandler<any> = {
  get(target: CollectionTypes, key: string | symbol, receiver: CollectionTypes) {
    // 拦截size访问
    if (key === 'size') {
      track(target, TrackOpTypes.ITERATE, ITERATE_KEY)
      return Reflect.get(target, key, target)
    }
    
    // 返回包装后的方法
    return mutableInstrumentations[key]
  }
}

// 集合方法的包装
const mutableInstrumentations: Record<string, Function> = {
  add(this: CollectionTypes, value: any) {
    const target = toRaw(this)
    const hadKey = target.has(value)
    
    const result = target.add(value)
    
    if (!hadKey) {
      trigger(target, TriggerOpTypes.ADD, value, value)
    }
    
    return result
  },
  
  delete(this: CollectionTypes, key: any) {
    const target = toRaw(this)
    const hadKey = target.has(key)
    
    const result = target.delete(key)
    
    if (hadKey) {
      trigger(target, TriggerOpTypes.DELETE, key, undefined, key)
    }
    
    return result
  },
  
  get(this: CollectionTypes, key: any) {
    const target = toRaw(this)
    
    // 依赖收集
    track(target, TrackOpTypes.GET, key)
    
    // 如果是Map,需要将值也响应化
    if (isMap(target)) {
      return wrap(target.get(key))
    }
    
    return target.get(key)
  },
  
  set(this: CollectionTypes, key: any, value: any) {
    const target = toRaw(this)
    const hadKey = target.has(key)
    const oldValue = target.get(key)
    
    // 设置值
    target.set(key, value)
    
    if (!hadKey) {
      trigger(target, TriggerOpTypes.ADD, key, value)
    } else if (hasChanged(value, oldValue)) {
      trigger(target, TriggerOpTypes.SET, key, value, oldValue)
    }
    
    return this
  }
}

依赖收集与追踪系统

// 全局状态
let activeEffect: ReactiveEffect | undefined
let shouldTrack = true
const targetMap = new WeakMap<any, KeyToDepMap>()

// 依赖收集
function track(target: object, type: TrackOpTypes, key: unknown) {
  if (!shouldTrack || activeEffect === undefined) {
    return
  }
  
  // 获取target对应的依赖Map
  let depsMap = targetMap.get(target)
  if (!depsMap) {
    targetMap.set(target, (depsMap = new Map()))
  }
  
  // 获取key对应的依赖Set
  let dep = depsMap.get(key)
  if (!dep) {
    depsMap.set(key, (dep = createDep()))
  }
  
  // 添加effect到依赖集合
  trackEffects(dep)
}

function trackEffects(dep: Dep) {
  // 避免重复收集
  if (!dep.has(activeEffect!)) {
    dep.add(activeEffect!)
    // effect也需要记录自己被哪些dep收集
    activeEffect!.deps.push(dep)
  }
}

// 触发更新
function trigger(
  target: object,
  type: TriggerOpTypes,
  key?: unknown,
  newValue?: unknown,
  oldValue?: unknown
) {
  const depsMap = targetMap.get(target)
  if (!depsMap) {
    return
  }
  
  // 收集所有需要触发的effect
  const effects: ReactiveEffect[] = []
  
  // 添加与key相关的effect
  if (key !== void 0) {
    const dep = depsMap.get(key)
    if (dep) {
      effects.push(...dep)
    }
  }
  
  // 特殊处理:数组length变化
  if (type === TriggerOpTypes.ADD && isArray(target)) {
    const lengthDep = depsMap.get('length')
    if (lengthDep) {
      effects.push(...lengthDep)
    }
  }
  
  // 添加与ITERATE_KEY相关的effect(用于for...in循环等)
  if (
    type === TriggerOpTypes.ADD ||
    type === TriggerOpTypes.DELETE ||
    (type === TriggerOpTypes.SET && target instanceof Map)
  ) {
    const iterateDep = depsMap.get(ITERATE_KEY)
    if (iterateDep) {
      effects.push(...iterateDep)
    }
  }
  
  // 特殊处理:Map的迭代
  if (
    (type === TriggerOpTypes.SET && target instanceof Map) ||
    (type === TriggerOpTypes.ADD && !isArray(target))
  ) {
    const keysDep = depsMap.get(MAP_KEY_ITERATE_KEY)
    if (keysDep) {
      effects.push(...keysDep)
    }
  }
  
  // 触发所有收集到的effect
  triggerEffects(createDep(effects))
}

function triggerEffects(dep: Dep) {
  // 触发所有effect
  for (const effect of dep) {
    if (effect !== activeEffect || effect.allowRecurse) {
      if (effect.scheduler) {
        // 如果有调度器,通过调度器执行
        effect.scheduler()
      } else {
        // 直接执行
        effect.run()
      }
    }
  }
}

Effect 系统实现

// Effect类定义
class ReactiveEffect<T = any> {
  active = true
  deps: Dep[] = []
  
  constructor(
    public fn: () => T,
    public scheduler: EffectScheduler | null = null,
    scope?: EffectScope
  ) {
    recordEffectScope(this, scope)
  }
  
  run() {
    if (!this.active) {
      return this.fn()
    }
    
    try {
      // 设置当前激活的effect
      activeEffect = this
      shouldTrack = true
      
      // 清理之前的依赖
      cleanupEffect(this)
      
      // 执行函数,期间会收集依赖
      return this.fn()
    } finally {
      // 恢复状态
      shouldTrack = false
      activeEffect = undefined
    }
  }
  
  stop() {
    if (this.active) {
      cleanupEffect(this)
      this.active = false
    }
  }
}

// 清理effect的依赖
function cleanupEffect(effect: ReactiveEffect) {
  const { deps } = effect
  if (deps.length) {
    for (let i = 0; i < deps.length; i++) {
      deps[i].delete(effect)
    }
    deps.length = 0
  }
}

// 创建effect
function effect<T = any>(
  fn: () => T,
  options?: ReactiveEffectOptions
): ReactiveEffectRunner {
  // 如果fn已经是effect,获取其原始函数
  if ((fn as any).effect) {
    fn = (fn as any).effect.fn
  }
  
  // 创建effect实例
  const _effect = new ReactiveEffect(fn)
  
  // 合并选项
  if (options) {
    extend(_effect, options)
    if (options.scope) {
      recordEffectScope(_effect, options.scope)
    }
  }
  
  // 如果没有设置lazy,立即执行
  if (!options || !options.lazy) {
    _effect.run()
  }
  
  // 返回runner
  const runner = _effect.run.bind(_effect) as ReactiveEffectRunner
  runner.effect = _effect
  return runner
}

// 停止effect
function stop(runner: ReactiveEffectRunner) {
  runner.effect.stop()
}

2.2 ref 与 computed 的实现原理

ref 的完整实现

// ref函数实现
function ref<T>(value: T): Ref<T> {
  return createRef(value, false)
}

// 创建ref的核心函数
function createRef(rawValue: unknown, shallow: boolean) {
  if (isRef(rawValue)) {
    return rawValue
  }
  
  return new RefImpl(rawValue, shallow)
}

// Ref实现类
class RefImpl<T> {
  private _value: T
  private _rawValue: T
  public readonly __v_isRef = true
  
  constructor(value: T, public readonly __v_isShallow: boolean) {
    // 保存原始值
    this._rawValue = __v_isShallow ? value : toRaw(value)
    
    // 如果是浅ref,直接使用值;否则转换为响应式
    this._value = __v_isShallow ? value : toReactive(value)
  }
  
  get value() {
    // 依赖收集
    trackRefValue(this)
    return this._value
  }
  
  set value(newVal) {
    // 使用原始值进行比较
    const useDirectValue = this.__v_isShallow || isShallow(newVal) || isReadonly(newVal)
    newVal = useDirectValue ? newVal : toRaw(newVal)
    
    if (hasChanged(newVal, this._rawValue)) {
      // 更新值
      this._rawValue = newVal
      this._value = useDirectValue ? newVal : toReactive(newVal)
      
      // 触发更新
      triggerRefValue(this, newVal)
    }
  }
}

// ref依赖收集
function trackRefValue(ref: RefBase<any>) {
  if (shouldTrack && activeEffect) {
    // 为ref创建一个特殊的key
    ref = toRaw(ref)
    
    // 获取或创建ref的依赖集合
    let dep = ref.dep
    if (!dep) {
      ref.dep = dep = createDep()
    }
    
    trackEffects(dep)
  }
}

// ref触发更新
function triggerRefValue(ref: RefBase<any>, newVal?: any) {
  ref = toRaw(ref)
  if (ref.dep) {
    triggerEffects(ref.dep)
  }
}

// toRef和toRefs的实现
function toRef<T extends object, K extends keyof T>(
  object: T,
  key: K
): ToRef<T[K]> {
  return new ObjectRefImpl(object, key) as any
}

class ObjectRefImpl<T extends object, K extends keyof T> {
  public readonly __v_isRef = true
  
  constructor(
    private readonly _object: T,
    private readonly _key: K
  ) {}
  
  get value() {
    return this._object[this._key]
  }
  
  set value(newVal) {
    this._object[this._key] = newVal
  }
}

// toRefs实现
function toRefs<T extends object>(object: T): ToRefs<T> {
  const ret: any = isArray(object) ? new Array(object.length) : {}
  
  for (const key in object) {
    ret[key] = toRef(object, key)
  }
  
  return ret
}

computed 的完整实现

// computed函数实现
function computed<T>(
  getterOrOptions: ComputedGetter<T> | WritableComputedOptions<T>
): ComputedRef<T> {
  let getter: ComputedGetter<T>
  let setter: ComputedSetter<T>
  
  // 处理两种参数形式
  if (isFunction(getterOrOptions)) {
    getter = getterOrOptions as ComputedGetter<T>
    setter = NOOP
  } else {
    getter = (getterOrOptions as WritableComputedOptions<T>).get
    setter = (getterOrOptions as WritableComputedOptions<T>).set
  }
  
  return new ComputedRefImpl(getter, setter, isFunction(getterOrOptions)) as any
}

// ComputedRef实现类
class ComputedRefImpl<T> {
  public dep?: Dep = undefined
  private _value!: T
  private _dirty = true
  public readonly effect: ReactiveEffect<T>
  public readonly __v_isRef = true
  public readonly [ReactiveFlags.IS_READONLY]: boolean
  
  constructor(
    private getter: ComputedGetter<T>,
    private readonly _setter: ComputedSetter<T>,
    isReadonly: boolean
  ) {
    // 创建effect,但立即不执行
    this.effect = new ReactiveEffect(
      () => getter(this._value),
      () => {
        // 调度器:当依赖变化时,标记为脏,并触发更新
        if (!this._dirty) {
          this._dirty = true
          triggerRefValue(this)
        }
      }
    )
    
    this.effect.computed = this
    this[ReactiveFlags.IS_READONLY] = isReadonly
  }
  
  get value() {
    // 依赖收集
    trackRefValue(this)
    
    // 如果脏,重新计算
    if (this._dirty) {
      this._dirty = false
      
      try {
        // 执行计算
        this._value = this.effect.run()!
      } catch (e) {
        // 计算出错时,标记为脏,下次重新计算
        this._dirty = true
        throw e
      }
    }
    
    return this._value
  }
  
  set value(newValue: T) {
    this._setter(newValue)
  }
}

// computed缓存机制
function computedWithCache<T>(
  getter: ComputedGetter<T>
): ComputedRef<T> {
  const computedRef = computed(getter)
  
  // 缓存上一次的计算结果
  let cachedValue: T | undefined
  let cachedDeps: Dep[] = []
  
  const effect = new ReactiveEffect(
    () => {
      const value = getter()
      
      // 检查依赖是否变化
      const deps = effect.deps.slice()
      
      if (cachedValue !== undefined) {
        // 比较依赖
        const depsChanged = deps.some((dep, i) => dep !== cachedDeps[i])
        if (!depsChanged) {
          return cachedValue
        }
      }
      
      // 更新缓存
      cachedValue = value
      cachedDeps = deps
      
      return value
    },
    // 调度器
    () => {
      // 清除缓存
      cachedValue = undefined
      cachedDeps = []
    }
  )
  
  return computedRef
}

2.3 watch 和 watchEffect 的实现

// watch函数实现
function watch<T = any>(
  source: WatchSource<T> | WatchSource<T>[],
  cb: WatchCallback<T>,
  options?: WatchOptions
): StopHandle {
  // 参数标准化
  const {
    immediate = false,
    deep = false,
    flush = 'pre',
    onTrack,
    onTrigger
  } = options || {}
  
  // 创建watcher实例
  const watcher = new Watcher(
    source,
    cb,
    {
      immediate,
      deep,
      flush,
      onTrack,
      onTrigger
    }
  )
  
  // 返回停止函数
  return () => watcher.stop()
}

// Watcher类实现
class Watcher<T = any> {
  private getter: () => T
  private cb: WatchCallback<T>
  private value?: T
  private oldValue?: T
  private active = true
  private cleanup?: () => void
  
  constructor(
    source: WatchSource<T> | WatchSource<T>[],
    cb: WatchCallback<T>,
    options: WatchOptionsInternal
  ) {
    // 1. 标准化回调函数
    this.cb = cb
    
    // 2. 创建getter函数
    if (isRef(source)) {
      // ref情况
      this.getter = () => source.value
    } else if (isReactive(source)) {
      // reactive情况
      this.getter = () => source
      options.deep = true // reactive默认深度监听
    } else if (isArray(source)) {
      // 数组情况
      this.getter = () =>
        source.map(s => {
          if (isRef(s)) {
            return s.value
          } else if (isReactive(s)) {
            return traverse(s)
          } else if (isFunction(s)) {
            return s()
          } else {
            warn(`无效的watch源`)
          }
        })
    } else if (isFunction(source)) {
      // 函数情况
      this.getter = source as () => T
    } else {
      // 默认情况
      this.getter = NOOP
    }
    
    // 3. 深度监听的处理
    if (options.deep) {
      const baseGetter = this.getter
      this.getter = () => traverse(baseGetter())
    }
    
    // 4. 立即执行选项
    if (options.immediate) {
      this.run()
    } else {
      // 否则收集初始值
      this.oldValue = this.getter()
    }
    
    // 5. 创建effect
    this.effect = new ReactiveEffect(
      () => this.getter(),
      () => this.scheduleRun()
    )
    
    // 6. 收集依赖
    this.value = this.effect.run()
  }
  
  // 调度运行
  private scheduleRun() {
    if (!this.active) {
      return
    }
    
    const { flush } = this.options
    
    if (flush === 'sync') {
      // 同步执行
      this.run()
    } else if (flush === 'post') {
      // 在组件更新后执行
      queuePostFlushCb(this.run.bind(this))
    } else {
      // 默认:在组件更新前执行
      queueJob(this.run.bind(this))
    }
  }
  
  // 执行watch
  private run() {
    if (!this.active) {
      return
    }
    
    // 获取新值
    const newValue = this.effect.run()
    
    // 清理上一次的清理函数
    if (this.cleanup) {
      this.cleanup()
      this.cleanup = undefined
    }
    
    // 值变化时的处理
    if (
      newValue !== this.value ||
      isObject(newValue) ||
      options.deep
    ) {
      // 调用回调
      const callbackResult = this.cb(newValue, this.value, (cleanupFn) => {
        this.cleanup = cleanupFn
      })
      
      // 更新旧值
      this.oldValue = newValue
      this.value = newValue
      
      // 如果回调返回清理函数
      if (isFunction(callbackResult)) {
        this.cleanup = callbackResult
      }
    }
  }
  
  // 停止watch
  stop() {
    if (this.active) {
      this.active = false
      this.effect.stop()
      if (this.cleanup) {
        this.cleanup()
      }
    }
  }
}

// watchEffect实现
function watchEffect(
  effect: WatchEffect,
  options?: WatchOptionsBase
): StopHandle {
  return watch(
    effect,
    null,
    options as WatchOptions
  )
}

// 深度遍历函数(用于深度监听)
function traverse(value: unknown, seen?: Set<unknown>): unknown {
  // 如果不是对象或者是null,直接返回
  if (!isObject(value) || value === null) {
    return value
  }
  
  // 避免循环引用
  seen = seen || new Set()
  if (seen.has(value)) {
    return value
  }
  seen.add(value)
  
  // 递归遍历
  if (isArray(value)) {
    for (let i = 0; i < value.length; i++) {
      traverse(value[i], seen)
    }
  } else if (value instanceof Map) {
    value.forEach((val, key) => {
      traverse(val, seen)
    })
  } else if (value instanceof Set) {
    value.forEach(val => {
      traverse(val, seen)
    })
  } else {
    // 普通对象
    for (const key in value) {
      traverse((value as any)[key], seen)
    }
  }
  
  return value
}

第三章:编译系统与模板优化

3.1 模板编译器架构

Vue 3 的编译器是完全重写的,支持编译时优化(Compile-time Optimization)。

编译器架构图

编译流程:
模板字符串
    ↓
解析器(Parser)
    ↓ 生成AST
抽象语法树(AST)
    ↓
转换器(Transformer)
    ↓ 静态提升、Patch Flag等优化
优化后的AST
    ↓
代码生成器(Codegen)
    ↓ 生成渲染函数
渲染函数字符串

解析器实现(简化版)

// 解析器状态
interface ParserContext {
  source: string
  offset: number
  line: number
  column: number
  inPre: boolean
  inVPre: boolean
}

// 解析器主函数
function parse(template: string): RootNode {
  const context = createParserContext(template)
  return parseChildren(context, [])
}

// 解析子节点
function parseChildren(
  context: ParserContext,
  ancestors: ElementNode[]
): TemplateChildNode[] {
  const nodes: TemplateChildNode[] = []
  
  while (!isEnd(context, ancestors)) {
    const s = context.source
    let node: TemplateChildNode | undefined
    
    if (startsWith(s, '{{')) {
      // 插值表达式
      node = parseInterpolation(context)
    } else if (s[0] === '<') {
      if (s[1] === '/') {
        // 结束标签
        parseTag(context, TagType.End, ancestors)
        continue
      } else if (/[a-z]/i.test(s[1])) {
        // 元素标签
        node = parseElement(context, ancestors)
      }
    }
    
    if (!node) {
      // 文本节点
      node = parseText(context)
    }
    
    pushNode(nodes, node)
  }
  
  return nodes
}

// 解析元素
function parseElement(
  context: ParserContext,
  ancestors: ElementNode[]
): ElementNode | undefined {
  // 1. 解析开始标签
  const element = parseTag(context, TagType.Start)
  
  if (element.isSelfClosing) {
    return element
  }
  
  // 2. 解析子节点
  ancestors.push(element)
  const children = parseChildren(context, ancestors)
  ancestors.pop()
  
  element.children = children
  
  // 3. 解析结束标签
  parseTag(context, TagType.End)
  
  return element
}

// 解析标签
function parseTag(
  context: ParserContext,
  type: TagType,
  ancestors?: ElementNode[]
): ElementNode {
  // 匹配标签
  const match = /^<\/?([a-z][^\t\r\n\f />]*)/i.exec(context.source)!
  const tag = match[1]
  
  // 前进到标签名后
  advanceBy(context, match[0].length)
  
  // 解析属性
  const props = parseAttributes(context)
  
  // 检查是否自闭合
  const isSelfClosing = startsWith(context.source, '/>')
  advanceBy(context, isSelfClosing ? 2 : 1)
  
  return {
    type: NodeTypes.ELEMENT,
    tag,
    props,
    children: [],
    isSelfClosing
  }
}

转换器实现

// 转换器上下文
interface TransformContext {
  root: RootNode
  parent: ParentNode | null
  currentNode: RootNode | TemplateChildNode | null
  helpers: Set<symbol>
  hoists: (JSChildNode | null)[]
  cached: number[]
  identifiers: { [name: string]: number | undefined }
  
  // 方法
  helper(name: string): symbol
  hoist(exp: JSChildNode): string
  cache(exp: JSChildNode, isVNode?: boolean): string
}

// 主转换函数
function transform(root: RootNode, options: TransformOptions) {
  const context = createTransformContext(root, options)
  
  // 遍历AST
  traverseNode(root, context)
  
  // 创建根代码生成节点
  root.codegenNode = createRootCodegenNode(root, context)
  
  // 应用元信息
  root.helpers = [...context.helpers]
  root.hoists = context.hoists
  root.components = context.components
  root.directives = context.directives
  root.imports = context.imports
  root.cached = context.cached
}

// 遍历节点
function traverseNode(
  node: RootNode | TemplateChildNode,
  context: TransformContext
) {
  context.currentNode = node
  
  // 应用节点转换
  const { nodeTransforms } = context
  const exitFns: (() => void)[] = []
  
  for (let i = 0; i < nodeTransforms.length; i++) {
    const onExit = nodeTransforms[i](node, context)
    if (onExit) {
      exitFns.push(onExit)
    }
    
    if (!context.currentNode) {
      // 节点被移除
      return
    } else {
      node = context.currentNode
    }
  }
  
  switch (node.type) {
    case NodeTypes.INTERPOLATION:
      // 处理插值表达式
      break
      
    case NodeTypes.ELEMENT:
    case NodeTypes.ROOT:
      // 遍历子节点
      traverseChildren(node, context)
      break
  }
  
  // 执行退出函数
  let i = exitFns.length
  while (i--) {
    exitFns[i]()
  }
}

// 关键转换:静态提升(Static Hoisting)
const transformHoist: NodeTransform = (node, context) => {
  if (node.type === NodeTypes.ELEMENT) {
    // 检查是否可以进行静态提升
    if (isStaticNode(node)) {
      // 生成静态节点
      const hoisted = createVNodeCall(
        context.helper(CREATE_VNODE),
        node.tag,
        node.props,
        node.children
      )
      
      // 添加到提升列表
      context.hoists.push(hoisted)
      
      // 替换为引用
      node.codegenNode = context.helper(CREATE_HOIST)
    }
  }
}

// 关键转换:Patch Flags
const transformElement: NodeTransform = (node, context) => {
  if (node.type === NodeTypes.ELEMENT) {
    return function postTransformElement() {
      const vnodeTag = `"${node.tag}"`
      const vnodeProps = buildProps(node, context)
      const vnodeChildren = node.children
      
      // 分析Patch Flags
      let patchFlag = 0
      if (vnodeProps.dynamicProps) {
        patchFlag |= PatchFlags.FULL_PROPS
      }
      if (hasDynamicKeys(vnodeProps)) {
        patchFlag |= PatchFlags.PROPS
      }
      if (node.children.length > 0) {
        patchFlag |= PatchFlags.TEXT
      }
      
      node.codegenNode = createVNodeCall(
        context.helper(CREATE_VNODE),
        vnodeTag,
        vnodeProps,
        vnodeChildren,
        patchFlag
      )
    }
  }
}

// 创建VNode调用
function createVNodeCall(
  context: TransformContext,
  tag: string,
  props?: PropsExpression,
  children?: TemplateChildNode[],
  patchFlag?: number,
  dynamicProps?: string[]
): VNodeCall {
  return {
    type: NodeTypes.VNODE_CALL,
    tag,
    props,
    children,
    patchFlag,
    dynamicProps
  }
}

代码生成器实现

// 代码生成器上下文
interface CodegenContext {
  source: string
  code: string
  line: number
  column: number
  offset: number
  
  // 方法
  push(code: string, node?: CodegenNode): void
  indent(): void
  deindent(): void
  newline(): void
}

// 生成代码
function generate(
  ast: RootNode,
  options: CodegenOptions = {}
): CodegenResult {
  const context = createCodegenContext(ast, options)
  const { push, indent, deindent, newline } = context
  
  // 生成导入语句
  genFunctionPreamble(ast, context)
  
  // 生成渲染函数
  push(`function render(_ctx, _cache) {`)
  indent()
  
  // 生成with语句(开发模式)或直接引用(生产模式)
  if (!options.isBrowser) {
    push(`with (_ctx) {`)
    indent()
  }
  
  // 生成hoisted变量的声明
  if (ast.hoists.length) {
    genHoists(ast.hoists, context)
    newline()
  }
  
  // 生成返回语句
  push(`return `)
  if (ast.codegenNode) {
    genNode(ast.codegenNode, context)
  } else {
    push(`null`)
  }
  
  if (!options.isBrowser) {
    deindent()
    push(`}`)
  }
  
  deindent()
  push(`}`)
  
  return {
    code: context.code,
    ast,
    map: context.map
  }
}

// 生成节点
function genNode(node: CodegenNode, context: CodegenContext) {
  switch (node.type) {
    case NodeTypes.ELEMENT:
    case NodeTypes.VNODE_CALL:
      genVNodeCall(node, context)
      break
      
    case NodeTypes.TEXT:
      genText(node, context)
      break
      
    case NodeTypes.INTERPOLATION:
      genInterpolation(node, context)
      break
      
    case NodeTypes.COMPOUND_EXPRESSION:
      genCompoundExpression(node, context)
      break
  }
}

// 生成VNode调用
function genVNodeCall(node: VNodeCall, context: CodegenContext) {
  const { push, helper } = context
  const { tag, props, children, patchFlag, dynamicProps } = node
  
  // 调用createVNode或createElementVNode(优化版本)
  const callHelper = patchFlag ? helper(CREATE_ELEMENT_VNODE) : helper(CREATE_VNODE)
  
  push(`${callHelper}(`)
  
  // tag
  genNode(tag, context)
  
  // props
  if (props) {
    push(`, `)
    genNode(props, context)
  } else {
    push(`, null`)
  }
  
  // children
  if (children) {
    push(`, `)
    if (Array.isArray(children)) {
      genNodeList(children, context)
    } else {
      genNode(children, context)
    }
  } else if (patchFlag) {
    push(`, null`)
  }
  
  // patchFlag和dynamicProps
  if (patchFlag) {
    push(`, ${patchFlag}`)
    if (dynamicProps) {
      push(`, `)
      genNodeList(dynamicProps, context)
    }
  }
  
  push(`)`)
}

// 生成静态提升
function genHoists(hoists: (JSChildNode | null)[], context: CodegenContext) {
  const { push, newline } = context
  
  push(`const _hoisted = []`)
  newline()
  
  for (let i = 0; i < hoists.length; i++) {
    const hoist = hoists[i]
    if (hoist) {
      push(`_hoisted[${i}] = `)
      genNode(hoist, context)
      newline()
    }
  }
}

// 生成属性
function genProps(props: PropsExpression, context: CodegenContext) {
  if (!props || props.type === NodeTypes.JS_CALL_EXPRESSION) {
    // 动态属性
    genNode(props, context)
  } else {
    // 静态属性
    push(`{ `)
    
    for (let i = 0; i < props.properties.length; i++) {
      const prop = props.properties[i]
      
      // key
      push(`${prop.key}: `)
      
      // value
      if (prop.value.type === NodeTypes.SIMPLE_EXPRESSION) {
        const { content, isStatic } = prop.value
        if (isStatic) {
          push(JSON.stringify(content))
        } else {
          push(content)
        }
      } else {
        genNode(prop.value, context)
      }
      
      if (i < props.properties.length - 1) {
        push(`, `)
      }
    }
    
    push(` }`)
  }
}

3.2 编译时优化详解

Patch Flags 系统

// Patch Flags 枚举
export const enum PatchFlags {
  TEXT = 1,                    // 动态文本内容
  CLASS = 1 << 1,              // 动态class
  STYLE = 1 << 2,              // 动态style
  PROPS = 1 << 3,              // 动态props(不包括class/style)
  FULL_PROPS = 1 << 4,         // 有动态key的props
  HYDRATE_EVENTS = 1 << 5,     // 带事件监听器
  STABLE_FRAGMENT = 1 << 6,    // 子节点顺序不会改变的Fragment
  KEYED_FRAGMENT = 1 << 7,     // 带key的Fragment
  UNKEYED_FRAGMENT = 1 << 8,   // 不带key的Fragment
  NEED_PATCH = 1 << 9,         // 只需要非props的patch
  DYNAMIC_SLOTS = 1 << 10,     // 动态slot
  DEV_ROOT_FRAGMENT = 1 << 11, // 开发环境的根Fragment
  
  // 特殊标志
  HOISTED = -1,                // 静态提升的节点
  BAIL = -2                    // 表示diff算法应该完全进行
}

// Patch Flag 分析器
function analyzePatchFlag(node: ElementNode): number {
  let patchFlag = 0
  
  // 分析props
  if (node.props.length > 0) {
    const hasDynamicProps = node.props.some(prop => {
      if (prop.type === NodeTypes.ATTRIBUTE) {
        // 静态属性
        return false
      } else if (prop.type === NodeTypes.DIRECTIVE) {
        // 指令
        return prop.name !== 'bind' || !prop.arg || prop.arg.isStatic
      }
      return true
    })
    
    if (hasDynamicProps) {
      patchFlag |= PatchFlags.PROPS
    }
  }
  
  // 分析class
  const classBinding = findProp(node, 'class')
  if (classBinding && classBinding.type === NodeTypes.DIRECTIVE) {
    patchFlag |= PatchFlags.CLASS
  }
  
  // 分析style
  const styleBinding = findProp(node, 'style')
  if (styleBinding && styleBinding.type === NodeTypes.DIRECTIVE) {
    patchFlag |= PatchFlags.STYLE
  }
  
  // 分析事件
  if (node.props.some(isEvent)) {
    patchFlag |= PatchFlags.HYDRATE_EVENTS
  }
  
  // 分析子节点
  if (node.children.length > 0) {
    const hasDynamicChildren = node.children.some(child => {
      return !isStaticNode(child)
    })
    
    if (hasDynamicChildren) {
      patchFlag |= PatchFlags.TEXT
    }
  }
  
  return patchFlag
}

// 静态节点分析
function isStaticNode(node: TemplateChildNode): boolean {
  switch (node.type) {
    case NodeTypes.ELEMENT:
      // 元素节点:检查所有属性和子节点是否都是静态的
      return node.props.every(isStaticProp) &&
             node.children.every(isStaticNode)
      
    case NodeTypes.TEXT:
      // 文本节点:总是静态的
      return true
      
    case NodeTypes.COMMENT:
      // 注释节点:总是静态的
      return true
      
    case NodeTypes.INTERPOLATION:
    case NodeTypes.COMPOUND_EXPRESSION:
      // 插值和复合表达式:动态的
      return false
      
    default:
      return false
  }
}

// 静态属性分析
function isStaticProp(prop: AttributeNode | DirectiveNode): boolean {
  if (prop.type === NodeTypes.ATTRIBUTE) {
    // 普通属性:静态
    return true
  }
  
  if (prop.type === NodeTypes.DIRECTIVE) {
    // 指令:检查是否绑定
    if (prop.name === 'bind') {
      // v-bind:检查参数和表达式是否静态
      const { arg, exp } = prop
      return (!arg || arg.isStatic) &&
             (!exp || exp.isStatic)
    }
    
    // 其他指令:动态
    return false
  }
  
  return false
}

静态提升优化

// 静态提升分析
function analyzeStatic(node: RootNode, context: TransformContext) {
  // 递归分析所有节点
  walk(node, {
    // 进入节点
    enter(node, parent) {
      if (node.type === NodeTypes.ELEMENT) {
        // 检查是否可以提升
        if (canHoist(node)) {
          // 标记为静态提升
          node.hoisted = true
          
          // 添加到提升列表
          const hoisted = createHoistedNode(node)
          context.hoists.push(hoisted)
          
          // 替换节点引用
          replaceNode(node, parent, createHoistedRef(hoisted))
        }
      }
    }
  })
}

// 检查节点是否可以提升
function canHoist(node: ElementNode): boolean {
  // 1. 不能有动态属性
  if (node.props.some(isDynamicProp)) {
    return false
  }
  
  // 2. 不能有指令(除了静态的v-bind)
  if (node.props.some(prop => 
    prop.type === NodeTypes.DIRECTIVE && 
    prop.name !== 'bind'
  )) {
    return false
  }
  
  // 3. 不能有动态子节点
  if (node.children.some(child => !isStaticNode(child))) {
    return false
  }
  
  // 4. 不能是组件
  if (isComponent(node.tag)) {
    return false
  }
  
  return true
}

// 创建提升节点
function createHoistedNode(node: ElementNode): HoistedNode {
  // 提取静态属性
  const staticProps = node.props.filter(isStaticProp)
  
  // 提取静态子节点
  const staticChildren = node.children.filter(isStaticNode)
  
  return {
    type: NodeTypes.HOISTED,
    props: staticProps,
    children: staticChildren,
    codegenNode: null
  }
}

// 生成提升节点的代码
function genHoistedNode(node: HoistedNode, context: CodegenContext) {
  const { push, helper } = context
  
  // 调用createStaticVNode
  push(`${helper(CREATE_STATIC_VNODE)}(`)
  
  // 生成静态内容
  push(`[`)
  
  // 生成标签
  push(`"${node.tag}"`)
  
  // 生成属性
  if (node.props.length > 0) {
    push(`, `)
    genProps(node.props, context)
  }
  
  // 生成子节点
  if (node.children.length > 0) {
    push(`, `)
    genNodeList(node.children, context)
  }
  
  push(`]`)
  push(`)`)
}

树结构压平优化

// 树结构压平分析
function analyzeTreeFlattening(node: ElementNode): boolean {
  // 检查是否可以进行树结构压平
  if (!node.children || node.children.length === 0) {
    return false
  }
  
  // 1. 必须是Fragment或div等容器元素
  if (!isFragmentLike(node)) {
    return false
  }
  
  // 2. 不能有动态props
  if (hasDynamicProps(node)) {
    return false
  }
  
  // 3. 不能有条件或循环
  if (hasConditionalOrLoop(node)) {
    return false
  }
  
  // 4. 检查子节点是否都是静态或只有一层嵌套
  let canFlatten = true
  let dynamicChildCount = 0
  
  for (const child of node.children) {
    if (isStaticNode(child)) {
      continue
    }
    
    if (child.type === NodeTypes.ELEMENT) {
      // 嵌套元素
      if (isFragmentLike(child)) {
        // 嵌套Fragment,可以合并
        dynamicChildCount += countDynamicChildren(child)
      } else {
        // 普通元素,计数+1
        dynamicChildCount++
      }
    } else {
      // 文本或插值
      dynamicChildCount++
    }
    
    if (dynamicChildCount > 10) {
      // 动态子节点太多,不适合压平
      canFlatten = false
      break
    }
  }
  
  return canFlatten
}

// 应用树结构压平
function flattenTree(node: ElementNode, context: TransformContext) {
  const flattenedChildren: TemplateChildNode[] = []
  
  // 递归压平子节点
  function flattenChildren(children: TemplateChildNode[]) {
    for (const child of children) {
      if (child.type === NodeTypes.ELEMENT && isFragmentLike(child)) {
        // 压平Fragment
        flattenChildren(child.children)
      } else {
        // 直接添加
        flattenedChildren.push(child)
      }
    }
  }
  
  flattenChildren(node.children)
  
  // 更新节点
  node.children = flattenedChildren
  node.patchFlag |= PatchFlags.STABLE_FRAGMENT
  
  // 标记为已压平
  node.flattened = true
}

// 在代码生成时处理压平
function genFlattenedVNodeCall(node: VNodeCall, context: CodegenContext) {
  const { push, helper } = context
  
  if (node.flattened) {
    // 生成压平的Fragment
    push(`${helper(CREATE_VNODE)}(`)
    push(`${helper(FRAGMENT)}, null, `)
    
    // 直接生成子节点数组
    push(`[`)
    genNodeList(node.children, context)
    push(`]`)
    
    push(`)`)
  } else {
    // 正常生成
    genVNodeCall(node, context)
  }
}

第四章:渲染系统与虚拟DOM

4.1 渲染器架构

渲染器核心实现

// 渲染器创建函数
function createRenderer(options: RendererOptions) {
  const {
    patchProp,
    insert,
    remove,
    createElement,
    createText,
    createComment,
    setText,
    setElementText,
    parentNode,
    nextSibling,
    querySelector
  } = options
  
  // 渲染函数
  const render: RootRenderFunction = (vnode, container) => {
    if (vnode == null) {
      // 卸载
      if (container._vnode) {
        unmount(container._vnode, null, null, true)
      }
    } else {
      // 挂载或更新
      patch(container._vnode || null, vnode, container)
    }
    
    // 保存vnode引用
    container._vnode = vnode
  }
  
  // 核心patch函数
  const patch: PatchFn = (
    n1, // 旧vnode
    n2, // 新vnode
    container,
    anchor = null,
    parentComponent = null,
    parentSuspense = null,
    namespace = undefined,
    slotScopeIds = null,
    optimized = false
  ) => {
    // 如果新旧vnode相同,直接返回
    if (n1 === n2) {
      return
    }
    
    // 如果类型不同,卸载旧节点
    if (n1 && !isSameVNodeType(n1, n2)) {
      anchor = getNextHostNode(n1)
      unmount(n1, parentComponent, parentSuspense, true)
      n1 = null
    }
    
    const { type, ref, shapeFlag } = n2
    
    switch (type) {
      case Text:
        // 处理文本节点
        processText(n1, n2, container, anchor)
        break
        
      case Comment:
        // 处理注释节点
        processCommentNode(n1, n2, container, anchor)
        break
        
      case Static:
        // 处理静态节点
        if (n1 == null) {
          mountStaticNode(n2, container, anchor)
        }
        break
        
      case Fragment:
        // 处理Fragment
        processFragment(
          n1,
          n2,
          container,
          anchor,
          parentComponent,
          parentSuspense,
          namespace,
          slotScopeIds,
          optimized
        )
        break
        
      default:
        if (shapeFlag & ShapeFlags.ELEMENT) {
          // 处理元素节点
          processElement(
            n1,
            n2,
            container,
            anchor,
            parentComponent,
            parentSuspense,
            namespace,
            slotScopeIds,
            optimized
          )
        } else if (shapeFlag & ShapeFlags.COMPONENT) {
          // 处理组件
          processComponent(
            n1,
            n2,
            container,
            anchor,
            parentComponent,
            parentSuspense,
            namespace,
            slotScopeIds,
            optimized
          )
        } else if (shapeFlag & ShapeFlags.TELEPORT) {
          // 处理Teleport
          ;(type as typeof TeleportImpl).process(
            n1,
            n2,
            container,
            anchor,
            parentComponent,
            parentSuspense,
            namespace,
            slotScopeIds,
            optimized,
            internals
          )
        } else if (__FEATURE_SUSPENSE__ && shapeFlag & ShapeFlags.SUSPENSE) {
          // 处理Suspense
          ;(type as typeof SuspenseImpl).process(
            n1,
            n2,
            container,
            anchor,
            parentComponent,
            parentSuspense,
            namespace,
            slotScopeIds,
            optimized,
            internals
          )
        }
    }
    
    // 处理ref
    if (ref != null && parentComponent) {
      setRef(ref, n1 && n1.ref, parentComponent, parentSuspense, n2)
    }
  }
  
  // 处理元素节点
  const processElement = (
    n1: VNode | null,
    n2: VNode,
    container: RendererElement,
    anchor: RendererNode | null,
    parentComponent: ComponentInternalInstance | null,
    parentSuspense: SuspenseBoundary | null,
    namespace: ElementNamespace,
    slotScopeIds: string[] | null,
    optimized: boolean
  ) => {
    if (n1 == null) {
      // 挂载
      mountElement(
        n2,
        container,
        anchor,
        parentComponent,
        parentSuspense,
        namespace,
        slotScopeIds,
        optimized
      )
    } else {
      // 更新
      patchElement(
        n1,
        n2,
        parentComponent,
        parentSuspense,
        namespace,
        slotScopeIds,
        optimized
      )
    }
  }
  
  // 挂载元素
  const mountElement = (
    vnode: VNode,
    container: RendererElement,
    anchor: RendererNode | null,
    parentComponent: ComponentInternalInstance | null,
    parentSuspense: SuspenseBoundary | null,
    namespace: ElementNamespace,
    slotScopeIds: string[] | null,
    optimized: boolean
  ) => {
    let el: RendererElement
    let vnodeHook: VNodeHook | undefined | null
    
    const { type, props, shapeFlag, transition, scopeId, patchFlag, dirs } = vnode
    
    // 创建DOM元素
    el = vnode.el = createElement(type as string, namespace)
    
    // 设置文本内容
    if (shapeFlag & ShapeFlags.TEXT_CHILDREN) {
      setElementText(el, vnode.children as string)
    } else if (shapeFlag & ShapeFlags.ARRAY_CHILDREN) {
      // 挂载子节点
      mountChildren(
        vnode.children as VNodeArrayChildren,
        el,
        null,
        parentComponent,
        parentSuspense,
        namespace,
        slotScopeIds,
        optimized
      )
    }
    
    // 设置props
    if (props) {
      for (const key in props) {
        if (key !== 'value' && !isReservedProp(key)) {
          patchProp(el, key, null, props[key], namespace)
        }
      }
      
      // 特殊处理value属性
      if ('value' in props) {
        patchProp(el, 'value', null, props.value, namespace)
      }
    }
    
    // 设置scope id
    if (scopeId) {
      setScopeId(el, scopeId)
    }
    
    // 执行指令
    if (dirs) {
      invokeDirectiveHook(vnode, null, parentComponent, 'beforeMount')
    }
    
    // 触发vnode hook
    if ((vnodeHook = props && props.onVnodeBeforeMount)) {
      invokeVNodeHook(vnodeHook, parentComponent, vnode)
    }
    
    // 插入到DOM
    insert(el, container, anchor)
    
    // 执行transition
    if (transition && !transition.persisted) {
      transition.enter(el)
    }
    
    // 执行指令的mounted钩子
    if (dirs) {
      invokeDirectiveHook(vnode, null, parentComponent, 'mounted')
    }
    
    // 触发vnode hook
    if ((vnodeHook = props && props.onVnodeMounted)) {
      invokeVNodeHook(vnodeHook, parentComponent, vnode)
    }
  }
  
  // 更新元素
  const patchElement = (
    n1: VNode,
    n2: VNode,
    parentComponent: ComponentInternalInstance | null,
    parentSuspense: SuspenseBoundary | null,
    namespace: ElementNamespace,
    slotScopeIds: string[] | null,
    optimized: boolean
  ) => {
    const el = (n2.el = n1.el!)
    let { patchFlag, dynamicChildren, dirs } = n2
    
    // 旧的props
    const oldProps = n1.props || EMPTY_OBJ
    // 新的props
    const newProps = n2.props || EMPTY_OBJ
    
    // 执行beforeUpdate钩子
    if ((n2Hook = newProps.onVnodeBeforeUpdate)) {
      invokeVNodeHook(n2Hook, parentComponent, n2, n1)
    }
    
    if (dirs) {
      invokeDirectiveHook(n2, n1, parentComponent, 'beforeUpdate')
    }
    
    // 优化:如果有dynamicChildren,只更新动态部分
    if (dynamicChildren && optimized) {
      patchBlockChildren(
        n1.dynamicChildren!,
        dynamicChildren,
        el,
        parentComponent,
        parentSuspense,
        namespace,
        slotScopeIds
      )
    } else if (!optimized) {
      // 完全diff
      patchChildren(
        n1,
        n2,
        el,
        null,
        parentComponent,
        parentSuspense,
        namespace,
        slotScopeIds,
        false
      )
    }
    
    // 更新props
    if (patchFlag > 0) {
      // 有patchFlag,根据标志更新
      if (patchFlag & PatchFlags.FULL_PROPS) {
        // 全量更新props
        patchProps(
          el,
          n2,
          oldProps,
          newProps,
          parentComponent,
          parentSuspense,
          namespace
        )
      } else {
        // 部分更新
        if (patchFlag & PatchFlags.CLASS) {
          if (oldProps.class !== newProps.class) {
            patchProp(el, 'class', null, newProps.class, namespace)
          }
        }
        
        if (patchFlag & PatchFlags.STYLE) {
          patchProp(el, 'style', oldProps.style, newProps.style, namespace)
        }
        
        if (patchFlag & PatchFlags.PROPS) {
          // 更新动态props
          const propsToUpdate = n2.dynamicProps!
          for (let i = 0; i < propsToUpdate.length; i++) {
            const key = propsToUpdate[i]
            const prev = oldProps[key]
            const next = newProps[key]
            if (next !== prev || key === 'value') {
              patchProp(el, key, prev, next, namespace)
            }
          }
        }
      }
    } else if (!optimized && dynamicChildren == null) {
      // 没有优化,全量diff props
      patchProps(
        el,
        n2,
        oldProps,
        newProps,
        parentComponent,
        parentSuspense,
        namespace
      )
    }
    
    // 执行updated钩子
    if ((n2Hook = newProps.onVnodeUpdated)) {
      queuePostRenderEffect(() => {
        invokeVNodeHook(n2Hook!, parentComponent, n2, n1)
      }, parentSuspense)
    }
    
    if (dirs) {
      invokeDirectiveHook(n2, n1, parentComponent, 'updated')
    }
  }
  
  return {
    render,
    hydrate,
    createApp: createAppAPI(render, hydrate)
  }
}

4.2 虚拟DOM Diff算法

Diff算法的核心实现

// 核心diff算法
function patchKeyedChildren(
  c1: VNode[],
  c2: VNodeArrayChildren,
  container: RendererElement,
  parentAnchor: RendererNode | null,
  parentComponent: ComponentInternalInstance | null,
  parentSuspense: SuspenseBoundary | null,
  namespace: ElementNamespace,
  slotScopeIds: string[] | null,
  optimized: boolean
) {
  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] as VNode
    
    if (isSameVNodeType(n1, n2)) {
      patch(
        n1,
        n2,
        container,
        null,
        parentComponent,
        parentSuspense,
        namespace,
        slotScopeIds,
        optimized
      )
    } else {
      break
    }
    i++
  }
  
  // 2. 从后面开始比较
  while (i <= e1 && i <= e2) {
    const n1 = c1[e1]
    const n2 = c2[e2] as VNode
    
    if (isSameVNodeType(n1, n2)) {
      patch(
        n1,
        n2,
        container,
        null,
        parentComponent,
        parentSuspense,
        namespace,
        slotScopeIds,
        optimized
      )
    } else {
      break
    }
    e1--
    e2--
  }
  
  // 3. 情况1:新节点更多(需要挂载)
  if (i > e1) {
    if (i <= e2) {
      const nextPos = e2 + 1
      const anchor = nextPos < l2 ? (c2[nextPos] as VNode).el : parentAnchor
      
      while (i <= e2) {
        patch(
          null,
          c2[i] as VNode,
          container,
          anchor,
          parentComponent,
          parentSuspense,
          namespace,
          slotScopeIds,
          optimized
        )
        i++
      }
    }
  }
  
  // 4. 情况2:旧节点更多(需要卸载)
  else if (i > e2) {
    while (i <= e1) {
      unmount(c1[i], parentComponent, parentSuspense, true)
      i++
    }
  }
  
  // 5. 情况3:未知序列(需要移动和patch)
  else {
    const s1 = i
    const s2 = i
    
    // 5.1 构建key到index的映射
    const keyToNewIndexMap: Map<string | number | symbol, number> = new Map()
    for (i = s2; i <= e2; i++) {
      const nextChild = c2[i] as VNode
      if (nextChild.key != null) {
        keyToNewIndexMap.set(nextChild.key, i)
      }
    }
    
    // 5.2 遍历旧节点
    let j
    let patched = 0
    const toBePatched = e2 - s2 + 1
    let moved = false
    let maxNewIndexSoFar = 0
    
    // 新节点在旧节点中的索引
    const newIndexToOldIndexMap = new Array(toBePatched)
    for (i = 0; i < toBePatched; i++) newIndexToOldIndexMap[i] = 0
    
    for (i = s1; i <= e1; i++) {
      const prevChild = c1[i]
      
      if (patched >= toBePatched) {
        // 所有新节点都已经patch,剩下的旧节点需要卸载
        unmount(prevChild, parentComponent, parentSuspense, true)
        continue
      }
      
      let newIndex
      if (prevChild.key != null) {
        newIndex = keyToNewIndexMap.get(prevChild.key)
      } else {
        // 没有key,需要遍历查找
        for (j = s2; j <= e2; j++) {
          if (
            newIndexToOldIndexMap[j - s2] === 0 &&
            isSameVNodeType(prevChild, c2[j] as VNode)
          ) {
            newIndex = j
            break
          }
        }
      }
      
      if (newIndex === undefined) {
        // 没有找到对应的新节点,卸载
        unmount(prevChild, parentComponent, parentSuspense, true)
      } else {
        // 更新映射
        newIndexToOldIndexMap[newIndex - s2] = i + 1
        
        if (newIndex >= maxNewIndexSoFar) {
          maxNewIndexSoFar = newIndex
        } else {
          moved = true
        }
        
        patch(
          prevChild,
          c2[newIndex] as VNode,
          container,
          null,
          parentComponent,
          parentSuspense,
          namespace,
          slotScopeIds,
          optimized
        )
        patched++
      }
    }
    
    // 5.3 移动和挂载
    const increasingNewIndexSequence = moved
      ? getSequence(newIndexToOldIndexMap)
      : EMPTY_ARR
    j = increasingNewIndexSequence.length - 1
    
    for (i = toBePatched - 1; i >= 0; i--) {
      const nextIndex = s2 + i
      const nextChild = c2[nextIndex] as VNode
      const anchor =
        nextIndex + 1 < l2 ? (c2[nextIndex + 1] as VNode).el : parentAnchor
      
      if (newIndexToOldIndexMap[i] === 0) {
        // 新节点,需要挂载
        patch(
          null,
          nextChild,
          container,
          anchor,
          parentComponent,
          parentSuspense,
          namespace,
          slotScopeIds,
          optimized
        )
      } else if (moved) {
        // 需要移动
        if (j < 0 || i !== increasingNewIndexSequence[j]) {
          move(nextChild, container, anchor, MoveType.REORDER)
        } else {
          j--
        }
      }
    }
  }
}

// 最长递增子序列算法(用于优化移动操作)
function getSequence(arr: number[]): number[] {
  const p = arr.slice()
  const result = [0]
  let i, j, u, v, c
  
  const len = arr.length
  for (i = 0; i < len; i++) {
    const arrI = arr[i]
    if (arrI !== 0) {
      j = result[result.length - 1]
      if (arr[j] < arrI) {
        p[i] = j
        result.push(i)
        continue
      }
      
      u = 0
      v = result.length - 1
      while (u < v) {
        c = (u + v) >> 1
        if (arr[result[c]] < arrI) {
          u = c + 1
        } else {
          v = c
        }
      }
      
      if (arrI < arr[result[u]]) {
        if (u > 0) {
          p[i] = result[u - 1]
        }
        result[u] = i
      }
    }
  }
  
  u = result.length
  v = result[u - 1]
  while (u-- > 0) {
    result[u] = v
    v = p[v]
  }
  
  return result
}

Patch Flag 在Diff中的优化应用

// 基于Patch Flag的优化diff
function patchBlockChildren(
  oldChildren: VNode[],
  newChildren: VNode[],
  fallbackContainer: RendererElement,
  parentComponent: ComponentInternalInstance | null,
  parentSuspense: SuspenseBoundary | null,
  namespace: ElementNamespace,
  slotScopeIds: string[] | null
) {
  for (let i = 0; i < newChildren.length; i++) {
    const oldVNode = oldChildren[i]
    const newVNode = newChildren[i]
    
    // 确定容器
    const container =
      oldVNode.el &&
      (oldVNode.type === Fragment ||
        isSameVNodeType(oldVNode, newVNode) ||
        oldVNode.shapeFlag & (ShapeFlags.COMPONENT | ShapeFlags.TELEPORT))
        ? parentNode(oldVNode.el)!
        : fallbackContainer
    
    patch(
      oldVNode,
      newVNode,
      container,
      null,
      parentComponent,
      parentSuspense,
      namespace,
      slotScopeIds,
      true // 优化模式
    )
  }
}

// 快速路径:处理静态节点
function patchStaticNode(
  n1: VNode | null,
  n2: VNode,
  container: RendererElement,
  anchor: RendererNode | null
) {
  if (n1 == null) {
    // 挂载静态节点
    n2.el = n1 ? n1.el : createStaticVNode(n2.children)
    insert(n2.el, container, anchor)
  }
  // 静态节点不需要更新
}

// 处理文本节点
function processText(
  n1: VNode | null,
  n2: VNode,
  container: RendererElement,
  anchor: RendererNode | null
) {
  if (n1 == null) {
    // 挂载
    n2.el = createText(n2.children as string)
    insert(n2.el, container, anchor)
  } else {
    // 更新
    const el = (n2.el = n1.el!)
    if (n2.children !== n1.children) {
      setText(el, n2.children as string)
    }
  }
}

第五章:组件系统与生命周期

5.1 组件实例化过程

组件实例的创建与初始化

// 创建组件实例
function createComponentInstance(
  vnode: VNode,
  parent: ComponentInternalInstance | null,
  suspense: SuspenseBoundary | null
): ComponentInternalInstance {
  const type = vnode.type as ConcreteComponent
  
  // 创建组件实例
  const instance: ComponentInternalInstance = {
    uid: uid++,
    vnode,
    type,
    parent,
    appContext: parent ? parent.appContext : vnode.appContext!,
    
    // 状态
    isMounted: false,
    isUnmounted: false,
    isDeactivated: false,
    
    // 响应式状态
    props: EMPTY_OBJ as any,
    attrs: EMPTY_OBJ,
    slots: EMPTY_OBJ,
    emit: null as any,
    
    // 生命周期
    ctx: EMPTY_OBJ,
    data: EMPTY_OBJ,
    setupState: EMPTY_OBJ,
    setupContext: null,
    
    // 渲染相关
    subTree: null!,
    update: null!,
    render: null,
    
    // 依赖注入
    provides: parent ? parent.provides : Object.create(appContext.provides),
    
    // 其他
    components: Object.create(type.components || null),
    directives: Object.create(type.directives || null),
    propsOptions: normalizePropsOptions(type, instance.appContext),
    emitsOptions: normalizeEmitsOptions(type, instance.appContext),
    
    // 代理
    proxy: null,
    exposed: null,
    exposeProxy: null,
    
    // 异步组件
    asyncDep: null,
    asyncResolved: false,
    
    // Suspense
    suspense,
    suspendId: suspense ? suspense.pendingId : 0,
    asyncDep: null,
    asyncResolved: false,
    
    // 错误处理
    error: null,
    
    // 缓存
    ce: null
  }
  
  // 开发环境额外属性
  if (__DEV__) {
    instance.ctx = createDevRenderContext(instance)
  } else {
    instance.ctx = { _: instance }
  }
  
  // 创建emit函数
  instance.emit = emit.bind(null, instance) as any
  
  // 创建代理
  instance.proxy = new Proxy(instance.ctx, PublicInstanceProxyHandlers)
  
  return instance
}

// 设置组件实例
function setupComponent(
  instance: ComponentInternalInstance,
  isSSR = false
) {
  isInSSRComponentSetup = isSSR
  
  const { props, children } = instance.vnode
  const isStateful = isStatefulComponent(instance)
  
  // 初始化props
  initProps(instance, props, isStateful, isSSR)
  
  // 初始化slots
  initSlots(instance, children)
  
  // 设置状态组件
  const setupResult = isStateful
    ? setupStatefulComponent(instance, isSSR)
    : undefined
  
  isInSSRComponentSetup = false
  
  return setupResult
}

// 设置状态组件
function setupStatefulComponent(
  instance: ComponentInternalInstance,
  isSSR: boolean
) {
  const Component = instance.type as ComponentOptions
  
  // 创建代理访问缓存
  instance.accessCache = Object.create(null)
  
  // 创建公共实例代理
  instance.proxy = markRaw(
    new Proxy(instance.ctx, PublicInstanceProxyHandlers)
  )
  
  // 执行setup函数
  const { setup } = Component
  if (setup) {
    const setupContext = (instance.setupContext =
      setup.length > 1 ? createSetupContext(instance) : null)
    
    // 设置当前实例
    currentInstance = instance
    
    // 暂停跟踪(setup中不跟踪依赖)
    pauseTracking()
    
    // 执行setup
    const setupResult = callWithErrorHandling(
      setup,
      instance,
      ErrorCodes.SETUP_FUNCTION,
      [__DEV__ ? shallowReadonly(instance.props) : instance.props, setupContext]
    )
    
    // 恢复跟踪
    resetTracking()
    currentInstance = null
    
    // 处理setup结果
    if (isPromise(setupResult)) {
      // 异步组件
      if (isSSR) {
        return setupResult.then((resolvedResult: unknown) => {
          handleSetupResult(instance, resolvedResult, isSSR)
        })
      } else if (__FEATURE_SUSPENSE__) {
        instance.asyncDep = setupResult
      } else {
        warn(
          `setup() returned a Promise, but the version of Vue you are using ` +
            `does not support it yet.`
        )
      }
    } else {
      handleSetupResult(instance, setupResult, isSSR)
    }
  } else {
    // 没有setup函数,完成组件设置
    finishComponentSetup(instance, isSSR)
  }
}

// 处理setup结果
function handleSetupResult(
  instance: ComponentInternalInstance,
  setupResult: unknown,
  isSSR: boolean
) {
  if (isFunction(setupResult)) {
    // setup返回渲染函数
    instance.render = setupResult as InternalRenderFunction
  } else if (isObject(setupResult)) {
    // setup返回对象,作为响应式状态
    if (__DEV__ && isVNode(setupResult)) {
      warn(
        `setup() should not return VNodes directly - ` +
          `return a render function instead.`
      )
    }
    
    // 将setup返回的状态设置为响应式
    instance.setupState = proxyRefs(setupResult)
  } else if (__DEV__ && setupResult !== undefined) {
    warn(
      `setup() should return an object. Received: ${setupResult === null ? 'null' : typeof setupResult}`
    )
  }
  
  // 完成组件设置
  finishComponentSetup(instance, isSSR)
}

// 完成组件设置
function finishComponentSetup(
  instance: ComponentInternalInstance,
  isSSR: boolean,
  skipOptions?: boolean
) {
  const Component = instance.type as ComponentOptions
  
  // 模板/渲染函数标准化
  if (!instance.render) {
    // 只有运行时编译时才编译模板
    if (!isSSR && compile && !Component.render) {
      const template = Component.template
      if (template) {
        // 编译模板
        const { isCustomElement, compilerOptions } = instance.appContext.config
        const { delimiters, compilerOptions: componentCompilerOptions } = Component
        
        const finalCompilerOptions: CompilerOptions = extend(
          extend(
            {
              isCustomElement,
              delimiters
            },
            compilerOptions
          ),
          componentCompilerOptions
        )
        
        // 编译
        Component.render = compile(template, finalCompilerOptions)
      }
    }
    
    // 设置渲染函数
    instance.render = (Component.render || NOOP) as InternalRenderFunction
    
    // 使用with块(运行时编译)
    if (instance.render._rc) {
      instance.withProxy = new Proxy(
        instance.ctx,
        RuntimeCompiledPublicInstanceProxyHandlers
      )
    }
  }
  
  // 兼容Options API
  if (__FEATURE_OPTIONS_API__ && !skipOptions) {
    setCurrentInstance(instance)
    pauseTracking()
    
    // 应用Options API
    applyOptions(instance)
    
    resetTracking()
    setCurrentInstance(null)
  }
  
  // 处理缺少渲染函数的情况
  if (__DEV__ && !instance.render && !isSSR) {
    if (!compile && Component.template) {
      warn(
        `Component provided template option but ` +
          `runtime compilation is not supported in this build of Vue.` +
          ` Use "vue.esm-browser.js" instead.`
      )
    } else {
      warn(`Component is missing template or render function.`)
    }
  }
}

5.2 生命周期实现

生命周期钩子的注册与调用

// 生命周期钩子类型
type LifecycleHook =
  | 'beforeCreate'
  | 'created'
  | 'beforeMount'
  | 'mounted'
  | 'beforeUpdate'
  | 'updated'
  | 'beforeUnmount'
  | 'unmounted'
  | 'renderTracked'
  | 'renderTriggered'
  | 'activated'
  | 'deactivated'
  | 'errorCaptured'
  | 'serverPrefetch'

// 生命周期钩子调用
function callHook(
  hook: LifecycleHook,
  instance: ComponentInternalInstance,
  args?: any[]
) {
  // 设置当前实例
  const prevInstance = currentInstance
  setCurrentInstance(instance)
  
  // 获取钩子函数
  const handlers = instance.type[hook]
  
  if (handlers) {
    // 调用所有注册的钩子
    for (let i = 0; i < handlers.length; i++) {
      invokeWithErrorHandling(
        handlers[i],
        instance,
        ErrorCodes.LIFECYCLE_HOOK,
        args
      )
    }
  }
  
  // 恢复之前的实例
  setCurrentInstance(prevInstance)
}

// Composition API生命周期注册
function injectHook(
  type: LifecycleHook,
  hook: Function & { __weh?: Function },
  target: ComponentInternalInstance | null = currentInstance,
  prepend: boolean = false
): Function | undefined {
  if (target) {
    // 获取或创建钩子数组
    const hooks = target[type] || (target[type] = [])
    
    // 包装钩子函数
    const wrappedHook =
      hook.__weh ||
      (hook.__weh = (...args: unknown[]) => {
        if (target.isUnmounted) {
          return
        }
        
        // 暂停跟踪
        pauseTracking()
        
        // 设置当前实例
        setCurrentInstance(target)
        
        // 调用钩子
        const res = callWithAsyncErrorHandling(hook, target, type, args)
        
        // 恢复当前实例
        setCurrentInstance(null)
        
        // 恢复跟踪
        resetTracking()
        
        return res
      })
    
    // 添加钩子
    if (prepend) {
      hooks.unshift(wrappedHook)
    } else {
      hooks.push(wrappedHook)
    }
    
    return wrappedHook
  } else if (__DEV__) {
    const apiName = `on${capitalize(type)}`
    warn(
      `${apiName} is called when there is no active component instance to be ` +
        `associated with. ` +
        `Lifecycle injection APIs can only be used during execution of setup().`
    )
  }
}

// 创建各种生命周期钩子函数
const createHook = (lifecycle: LifecycleHook) => {
  return (hook: Function, target: ComponentInternalInstance | null = currentInstance) =>
    injectHook(lifecycle, hook, target)
}

// 导出Composition API生命周期函数
export const onBeforeMount = createHook('beforeMount')
export const onMounted = createHook('mounted')
export const onBeforeUpdate = createHook('beforeUpdate')
export const onUpdated = createHook('updated')
export const onBeforeUnmount = createHook('beforeUnmount')
export const onUnmounted = createHook('unmounted')
export const onErrorCaptured = createHook('errorCaptured')
export const onRenderTracked = createHook('renderTracked')
export const onRenderTriggered = createHook('renderTriggered')
export const onActivated = createHook('activated')
export const onDeactivated = createHook('deactivated')

// 在组件挂载和更新时调用生命周期钩子
function componentUpdateFn() {
  if (!instance.isMounted) {
    // 挂载阶段
    let vnodeHook: VNodeHook | null | undefined
    
    // 调用beforeMount钩子
    if (__FEATURE_OPTIONS_API__) {
      callHook('beforeMount', instance)
    }
    
    // 执行渲染
    const subTree = (instance.subTree = renderComponentRoot(instance))
    
    // 挂载到容器
    patch(null, subTree, container, anchor, instance, parentSuspense, namespace)
    
    // 保存vnode
    initialVNode.el = subTree.el
    
    // 调用mounted钩子
    if (__FEATURE_OPTIONS_API__) {
      callHook('mounted', instance)
    }
    
    // 标记为已挂载
    instance.isMounted = true
    
    // 调用activated钩子(如果是从keep-alive中激活)
    if (initialVNode.shapeFlag & ShapeFlags.COMPONENT_SHOULD_KEEP_ALIVE) {
      instance.a && queuePostRenderEffect(instance.a, parentSuspense)
      callHook('activated', instance)
    }
  } else {
    // 更新阶段
    let { next, vnode } = instance
    
    // 调用beforeUpdate钩子
    if (__FEATURE_OPTIONS_API__) {
      callHook('beforeUpdate', instance)
    }
    
    // 更新vnode引用
    if (next) {
      next.el = vnode.el
      updateComponentPreRender(instance, next, optimized)
    }
    
    // 执行渲染
    const nextTree = renderComponentRoot(instance)
    
    // 保存之前的子树
    const prevTree = instance.subTree
    instance.subTree = nextTree
    
    // 执行patch更新
    patch(
      prevTree,
      nextTree,
      parentNode(prevTree.el!)!,
      getNextHostNode(prevTree),
      instance,
      parentSuspense,
      namespace
    )
    
    // 更新el引用
    next.el = nextTree.el
    
    // 调用updated钩子
    if (__FEATURE_OPTIONS_API__) {
      callHook('updated', instance)
    }
  }
}

5.3 组件更新调度

响应式更新与调度系统

// 组件更新函数
const componentUpdateFn = () => {
  if (!instance.isMounted) {
    // 初始挂载
    // ... 挂载逻辑
  } else {
    // 更新
    let { next, bu, u, parent, vnode } = instance
    
    // 调用beforeUpdate钩子
    if (bu) {
      invokeArrayFns(bu)
    }
    
    // 执行render生成vnode
    const nextTree = renderComponentRoot(instance)
    const prevTree = instance.subTree
    instance.subTree = nextTree
    
    // patch更新
    patch(
      prevTree,
      nextTree,
      // 父节点可能在teleport中
      hostParentNode(prevTree.el!)!,
      // 锚点
      getNextHostNode(prevTree),
      instance,
      parentSuspense,
      isSVG
    )
    
    // 更新el引用
    next.el = nextTree.el
    
    // 调用updated钩子
    if (u) {
      queuePostRenderEffect(u, parentSuspense)
    }
  }
}

// 创建组件effect
const effect = (instance.effect = new ReactiveEffect(
  componentUpdateFn,
  () => queueJob(update),
  instance.scope // 在组件effect作用域中跟踪它
))

// 组件更新函数
const update: SchedulerJob = (instance.update = () => effect.run())
update.id = instance.uid

// 调度器
const queue: SchedulerJob[] = []
let flushIndex = 0

// 队列任务
function queueJob(job: SchedulerJob) {
  if (
    !queue.length ||
    !queue.includes(job, isFlushing ? flushIndex + 1 : flushIndex)
  ) {
    // 将任务添加到队列
    if (job.id == null) {
      queue.push(job)
    } else {
      // 按id插入,确保父组件在子组件之前更新
      queue.splice(findInsertionIndex(job.id), 0, job)
    }
    
    // 刷新队列
    queueFlush()
  }
}

// 刷新队列
function queueFlush() {
  if (!isFlushing && !isFlushPending) {
    isFlushPending = true
    
    // 在微任务中执行刷新
    currentFlushPromise = resolvedPromise.then(flushJobs)
  }
}

// 执行队列中的任务
function flushJobs(seen?: CountMap) {
  isFlushPending = false
  isFlushing = true
  
  if (__DEV__) {
    seen = seen || new Map()
  }
  
  // 先执行预任务队列
  flushPreFlushCbs(seen)
  
  // 对队列排序:确保
  // 1. 组件从父到子更新(因为父组件总是在子组件之前创建)
  // 2. 如果父组件在更新期间卸载了组件,可以跳过它的更新
  queue.sort((a, b) => getId(a) - getId(b))
  
  try {
    for (flushIndex = 0; flushIndex < queue.length; flushIndex++) {
      const job = queue[flushIndex]
      
      if (job && job.active !== false) {
        if (__DEV__ && checkRecursiveUpdates(seen!, job)) {
          continue
        }
        
        // 执行任务
        callWithErrorHandling(job, null, ErrorCodes.SCHEDULER)
      }
    }
  } finally {
    // 重置状态
    flushIndex = 0
    queue.length = 0
    
    // 执行后置任务队列
    flushPostFlushCbs(seen)
    
    isFlushing = false
    currentFlushPromise = null
    
    // 如果在刷新期间有新的任务被添加,重新执行
    if (queue.length || pendingPostFlushCbs.length) {
      flushJobs(seen)
    }
  }
}

第六章:高级特性与性能优化

6.1 异步组件与Suspense

异步组件实现

// 定义异步组件
function defineAsyncComponent(
  source: AsyncComponentLoader | AsyncComponentOptions
): Component {
  if (isFunction(source)) {
    source = { loader: source }
  }
  
  const {
    loader,
    loadingComponent,
    errorComponent,
    delay = 200,
    timeout, // undefined = 永不超时
    suspensible = true,
    onError: userOnError
  } = source
  
  // 存储最近加载的组件
  let loadedComp: Component | undefined
  let error: Error | undefined
  let delayTimeout: NodeJS.Timeout | undefined
  let timeoutTimeout: NodeJS.Timeout | undefined
  
  // 加载状态
  let loading = false
  let loadingInstance: ComponentInternalInstance | null = null
  
  // 重试次数
  let retries = 0
  const retry = () => {
    retries++
    error = undefined
    return load()
  }
  
  // 加载函数
  const load = (): Promise<Component> => {
    let thisRequest: Promise<Component>
    
    return (
      loader()
        .then(comp => {
          // 处理ES模块默认导出
          if (
            comp &&
            (comp.__esModule || comp[Symbol.toStringTag] === 'Module')
          ) {
            comp = comp.default
          }
          
          // 开发环境检查
          if (__DEV__ && !isObject(comp) && !isFunction(comp)) {
            throw new Error(
              `无效的异步组件加载结果:${comp}. 期望一个对象或函数。`
            )
          }
          
          loadedComp = comp
          return comp
        })
        .catch(err => {
          error = err
          
          if (userOnError) {
            // 用户自定义错误处理
            return new Promise((resolve, reject) => {
              const userRetry = () => resolve(retry())
              const userFail = () => reject(err)
              
              userOnError(err, userRetry, userFail, retries + 1)
            })
          } else {
            throw err
          }
        })
    )
  }
  
  // 返回包装组件
  return defineComponent({
    name: 'AsyncComponentWrapper',
    __asyncLoader: load,
    __asyncResolved: false,
    
    setup() {
      const instance = currentInstance!
      
      // 如果已经加载,直接返回
      if (loadedComp) {
        return () => createInnerComp(loadedComp!, instance)
      }
      
      // 错误处理
      const onError = (err: Error) => {
        error = err
        loading = false
      }
      
      // 如果有延迟,设置定时器
      if (delay) {
        delayTimeout = setTimeout(() => {
          loading = true
          loadingInstance = instance
        }, delay)
      }
      
      // 如果超时
      if (timeout != null) {
        timeoutTimeout = setTimeout(() => {
          onError(new Error(`异步组件加载超时 (${timeout}ms)`))
        }, timeout)
      }
      
      // 执行加载
      load()
        .then(() => {
          if (!instance.isUnmounted) {
            // 清除定时器
            if (delayTimeout) {
              clearTimeout(delayTimeout)
              delayTimeout = undefined
            }
            
            if (timeoutTimeout) {
              clearTimeout(timeoutTimeout)
              timeoutTimeout = undefined
            }
            
            // 更新状态
            loading = false
            loadingInstance = null
            error = undefined
            loadedComp = loadedComp
          }
        })
        .catch(err => {
          onError(err)
        })
      
      // 返回渲染函数
      return () => {
        if (loadedComp && !error) {
          // 加载成功,渲染组件
          return createInnerComp(loadedComp, instance)
        } else if (error && errorComponent) {
          // 错误状态,渲染错误组件
          return createVNode(errorComponent, {
            error
          })
        } else if (loadingComponent && loading) {
          // 加载中,渲染加载组件
          return createVNode(loadingComponent)
        }
        
        // 默认返回注释节点
        return createVNode(Comment, null, 'async component')
      }
    }
  })
}

// 创建内部组件
function createInnerComp(
  comp: Component,
  parent: ComponentInternalInstance
) {
  // 解析出选项
  const { ref, props, children, ce } = parent.vnode
  const vnode = createVNode(comp, props, children)
  
  // 确保继承实例属性
  vnode.ref = ref
  vnode.ce = ce
  
  // 标记为已解析
  ;(vnode.type as ComponentOptions).__asyncResolved = true
  
  return vnode
}

Suspense实现

// Suspense组件实现
const SuspenseImpl = {
  name: 'Suspense',
  // 在Suspense边界内,Suspense有自己的vnode
  __isSuspense: true,
  
  process(
    n1: VNode | null,
    n2: VNode,
    container: RendererElement,
    anchor: RendererNode | null,
    parentComponent: ComponentInternalInstance | null,
    parentSuspense: SuspenseBoundary | null,
    namespace: ElementNamespace,
    slotScopeIds: string[] | null,
    optimized: boolean,
    rendererInternals: RendererInternals
  ) {
    if (n1 == null) {
      // 挂载Suspense
      mountSuspense(
        n2,
        container,
        anchor,
        parentComponent,
        parentSuspense,
        namespace,
        slotScopeIds,
        optimized,
        rendererInternals
      )
    } else {
      // 更新Suspense
      patchSuspense(
        n1,
        n2,
        container,
        anchor,
        parentComponent,
        namespace,
        slotScopeIds,
        optimized,
        rendererInternals
      )
    }
  }
}

// 挂载Suspense
function mountSuspense(
  vnode: VNode,
  container: RendererElement,
  anchor: RendererNode | null,
  parentComponent: ComponentInternalInstance | null,
  parentSuspense: SuspenseBoundary | null,
  namespace: ElementNamespace,
  slotScopeIds: string[] | null,
  optimized: boolean,
  rendererInternals: RendererInternals
) {
  const {
    p: patch,
    o: { createElement }
  } = rendererInternals
  
  // 创建隐藏容器
  const hiddenContainer = createElement('div')
  
  // 创建Suspense边界
  const suspense = (vnode.suspense = createSuspenseBoundary(
    vnode,
    parentSuspense,
    parentComponent,
    container,
    hiddenContainer,
    anchor,
    namespace,
    slotScopeIds,
    optimized,
    rendererInternals
  ))
  
  // 开始挂载
  suspense.pendingBranch = vnode.ssContent!
  suspense.isInFallback = false
  
  // 挂载默认内容
  patch(
    null,
    vnode.ssContent!,
    hiddenContainer,
    null,
    parentComponent,
    suspense,
    namespace,
    slotScopeIds,
    optimized
  )
  
  // 检查是否有异步依赖
  if (suspense.deps > 0) {
    // 有异步依赖,进入fallback状态
    suspense.isInFallback = true
    
    // 挂载fallback
    patch(
      null,
      vnode.ssFallback!,
      container,
      anchor,
      parentComponent,
      null, // fallback tree不会在Suspense边界内
      namespace,
      slotScopeIds,
      optimized
    )
    
    // 设置主内容为隐藏
    setActiveBranch(suspense, vnode.ssFallback!)
  } else {
    // 没有异步依赖,直接显示内容
    suspense.resolve()
  }
}

// 创建Suspense边界
function createSuspenseBoundary(
  vnode: VNode,
  parentSuspense: SuspenseBoundary | null,
  parentComponent: ComponentInternalInstance | null,
  container: RendererElement,
  hiddenContainer: RendererElement,
  anchor: RendererNode | null,
  namespace: ElementNamespace,
  slotScopeIds: string[] | null,
  optimized: boolean,
  rendererInternals: RendererInternals
): SuspenseBoundary {
  // 创建Suspense边界实例
  const suspense: SuspenseBoundary = {
    vnode,
    parent: parentSuspense,
    parentComponent,
    isSVG: namespace === 'svg',
    container,
    hiddenContainer,
    anchor,
    namespace,
    slotScopeIds,
    optimized,
    deps: 0,
    pendingBranch: null,
    pendingId: 0,
    isInFallback: true,
    isHydrating: false,
    isUnmounted: false,
    effects: [],
    
    // 方法
    resolve,
    fallback,
    move,
    next,
    registerDep,
    unmount,
    
    // 组件
    p: patch,
    um: unmount,
    r: remove,
    m: move,
    o: rendererInternals.o
  }
  
  return suspense
}

// 注册异步依赖
function registerDep(
  suspense: SuspenseBoundary,
  dep: AsyncDep,
  optimized: boolean
) {
  const loaded = dep.loaded
  
  if (suspense.isUnmounted) {
    return
  }
  
  // 记录异步依赖
  suspense.deps++
  
  // 监听加载完成
  dep
    .then(
      () => {
        if (suspense.isUnmounted || !dep.loaded) {
          return
        }
        
        dep.loaded = true
        suspense.deps--
        
        if (suspense.deps === 0) {
          // 所有依赖都加载完成
          if (!suspense.isInFallback) {
            suspense.resolve(false)
          } else if (suspense.pendingId === dep.__suspenseId) {
            // 当前pending的依赖,立即解析
            suspense.resolve()
          }
        }
      },
      err => {
        if (suspense.isUnmounted || !dep.loaded) {
          return
        }
        
        dep.loaded = true
        dep.error = err
        suspense.deps--
        
        // 处理错误
        if (suspense.deps === 0) {
          suspense.resolve()
        }
      }
    )
    .catch(() => {
      // 忽略错误
    })
}

// 解析Suspense
function resolve(
  suspense: SuspenseBoundary,
  isSync = false
) {
  const {
    vnode,
    pendingBranch: branch,
    parentComponent,
    container,
    hiddenContainer
  } = suspense
  
  if (suspense.isResolving || suspense.isUnmounted) {
    return
  }
  
  suspense.isResolving = true
  
  // 移除fallback
  if (suspense.isInFallback) {
    // 卸载fallback
    unmount(suspense.activeBranch!, parentComponent, suspense, true)
    
    if (!suspense.isHydrating) {
      // 移动隐藏的内容到容器
      move(
        branch,
        container,
        suspense.anchor,
        MoveType.ENTER,
        suspense.namespace
      )
    }
  }
  
  // 设置活动分支
  setActiveBranch(suspense, branch!)
  
  // 更新vnode el
  vnode.el = branch!.el
  
  // 检查是否已经挂载
  if (!branch!.mounted) {
    branch!.mounted = true
  }
  
  // 清空状态
  suspense.pendingBranch = null
  suspense.isInFallback = false
  suspense.isResolving = false
  
  // 执行effects
  flushPostFlushCbs()
  
  // 触发resolve事件
  if (parentComponent && parentComponent.vnode.shapeFlag & ShapeFlags.SUSPENSE) {
    parentComponent.emit('resolve')
  }
}

6.2 Teleport实现

// Teleport组件实现
const TeleportImpl = {
  __isTeleport: true,
  
  process(
    n1: VNode | null,
    n2: VNode,
    container: RendererElement,
    anchor: RendererNode | null,
    parentComponent: ComponentInternalInstance | null,
    parentSuspense: SuspenseBoundary | null,
    namespace: ElementNamespace,
    slotScopeIds: string[] | null,
    optimized: boolean,
    internals: RendererInternals
  ) {
    const {
      mc: mountChildren,
      pc: patchChildren,
      pbc: patchBlockChildren,
      o: { insert, querySelector, createText, createComment }
    } = internals
    
    const disabled = isTeleportDisabled(n2.props)
    const { shapeFlag, children } = n2
    
    // 移动到目标容器
    const target = (n2.target = resolveTarget(n2.props, querySelector))
    const targetAnchor = (n2.targetAnchor = createText(''))
    
    if (target) {
      // 插入目标锚点
      insert(targetAnchor, target)
    }
    
    if (disabled) {
      // 禁用状态:作为普通Fragment处理
      if (!n1) {
        // 挂载
        mountChildren(
          children as VNodeArrayChildren,
          container,
          anchor,
          parentComponent,
          parentSuspense,
          namespace,
          slotScopeIds,
          optimized
        )
      } else {
        // 更新
        patchChildren(
          n1,
          n2,
          container,
          anchor,
          parentComponent,
          parentSuspense,
          namespace,
          slotScopeIds,
          optimized
        )
      }
    } else {
      // Teleport启用状态
      if (!n1) {
        // 挂载
        // 在隐藏容器中挂载内容
        const placeholder = (n2.placeholder = createComment('teleport'))
        insert(placeholder, container, anchor)
        
        const mainAnchor = (n2.anchor = createComment('teleport'))
        insert(mainAnchor, container, anchor)
        
        const mount = (container: RendererElement, anchor: RendererNode) => {
          if (shapeFlag & ShapeFlags.ARRAY_CHILDREN) {
            mountChildren(
              children as VNodeArrayChildren,
              container,
              anchor,
              parentComponent,
              parentSuspense,
              namespace,
              slotScopeIds,
              optimized
            )
          }
        }
        
        if (target) {
          // 挂载到目标
          mount(target, targetAnchor)
        }
        
        // 更新占位符
        updateCssVars(n2)
      } else {
        // 更新
        ;(n2.anchor = n1.anchor)!
        ;(n2.targetAnchor = n1.targetAnchor)!
        
        // 更新内容
        if (n2.children !== n1.children) {
          const target = n2.target!
          const targetAnchor = n2.targetAnchor!
          
          // 更新子节点
          patchChildren(
            n1,
            n2,
            target,
            targetAnchor,
            parentComponent,
            parentSuspense,
            namespace,
            slotScopeIds,
            optimized
          )
        }
        
        // 更新CSS变量
        updateCssVars(n2)
      }
    }
  },
  
  remove(
    vnode: VNode,
    parentComponent: ComponentInternalInstance | null,
    parentSuspense: SuspenseBoundary | null,
    optimized: boolean,
    { um: unmount, o: { remove: hostRemove } }: RendererInternals,
    doRemove: boolean
  ) {
    const { shapeFlag, children, anchor, targetAnchor, target, disabled } = vnode
    
    if (target) {
      hostRemove(targetAnchor!)
    }
    
    // 卸载子节点
    if (doRemove || !isTeleportDisabled(vnode.props)) {
      hostRemove(anchor!)
      
      if (shapeFlag & ShapeFlags.ARRAY_CHILDREN) {
        for (let i = 0; i < (children as VNodeArrayChildren).length; i++) {
          const child = (children as VNodeArrayChildren)[i]
          unmount(
            child,
            parentComponent,
            parentSuspense,
            true,
            optimized
          )
        }
      }
    }
  },
  
  move: moveTeleport,
  hydrate: hydrateTeleport
}

// 移动Teleport
function moveTeleport(
  vnode: VNode,
  container: RendererElement,
  anchor: RendererNode | null,
  moveType: MoveType,
  parentSuspense: SuspenseBoundary | null = null
) {
  const { shapeFlag, children, disabled } = vnode
  
  if (disabled) {
    // 禁用状态:作为普通Fragment移动
    move(vnode, container, anchor, moveType, parentSuspense)
  } else {
    // 移动目标锚点
    const target = vnode.target!
    if (moveType === MoveType.ENTER) {
      insert(vnode.targetAnchor!, target)
    } else {
      insert(vnode.anchor!, container, anchor)
    }
    
    // 移动子节点
    if (shapeFlag & ShapeFlags.ARRAY_CHILDREN) {
      for (let i = 0; i < (children as VNodeArrayChildren).length; i++) {
        move(
          (children as VNodeArrayChildren)[i],
          target,
          vnode.targetAnchor!,
          moveType,
          parentSuspense
        )
      }
    }
  }
}

// 解析Teleport目标
function resolveTarget(props, querySelector): RendererElement | null {
  const targetSelector = props && props.to
  if (isString(targetSelector)) {
    if (!querySelector) {
      __DEV__ &&
        warn(
          `当前渲染器不支持querySelector。` +
            `Teleport的"to"属性必须是显式的DOM元素。`
        )
      return null
    }
    
    const target = querySelector(targetSelector)
    if (!target) {
      __DEV__ &&
        warn(
          `找不到Teleport的目标元素:${targetSelector}`
        )
      return null
    }
    
    return target
  } else {
    if (__DEV__ && !targetSelector) {
      warn(`无效的Teleport的"to"属性:${targetSelector}`)
    }
    return targetSelector
  }
}

第七章:性能优化与最佳实践

7.1 编译时性能优化

静态节点提升优化

// 静态节点分析器
function analyzeStaticNodes(root: RootNode): {
  hoisted: HoistedNode[]
  cached: number[]
} {
  const hoisted: HoistedNode[] = []
  const cached: number[] = []
  
  walk(root, {
    enter(node, parent) {
      // 标记静态节点
      if (isStaticNode(node)) {
        node.staticCount = (node.staticCount || 0) + 1
        
        // 如果是频繁出现的静态节点,考虑缓存
        if (node.staticCount > 3) {
          const cachedIndex = cached.indexOf(node.staticId)
          if (cachedIndex === -1) {
            cached.push(node.staticId)
            node.cached = true
          }
        }
      }
      
      // 检查是否可以提升
      if (canHoistNode(node)) {
        const hoistedNode = createHoistedNode(node)
        hoisted.push(hoistedNode)
        node.hoisted = true
      }
    }
  })
  
  return { hoisted, cached }
}

// 缓存策略
function applyCachingStrategy(
  node: TemplateChildNode,
  context: TransformContext
): string | null {
  if (node.cached) {
    // 生成缓存key
    const cacheKey = `_cache[${node.staticId}]`
    
    // 检查缓存是否已存在
    if (!context.cache[cacheKey]) {
      // 创建缓存
      context.cache[cacheKey] = createCachedNode(node)
      return cacheKey
    }
    
    return cacheKey
  }
  
  return null
}

// 事件处理优化
function transformEventHandlers(
  node: ElementNode,
  context: TransformContext
) {
  const events: Record<string, string> = {}
  
  // 收集事件处理函数
  for (const prop of node.props) {
    if (prop.type === NodeTypes.DIRECTIVE && prop.name === 'on') {
      const eventName = prop.arg?.content
      const handler = prop.exp
      
      if (eventName && handler) {
        events[eventName] = handler.content
        
        // 内联简单的事件处理函数
        if (isInlineableEventHandler(handler)) {
          prop.exp.content = inlineEventHandler(handler)
        }
      }
    }
  }
  
  // 应用事件委托优化
  if (Object.keys(events).length > 3) {
    // 多个事件,考虑使用事件委托
    applyEventDelegation(node, events, context)
  }
}

// 属性合并优化
function transformAttributes(
  node: ElementNode,
  context: TransformContext
) {
  const staticAttrs: AttributeNode[] = []
  const dynamicAttrs: DirectiveNode[] = []
  
  // 分离静态和动态属性
  for (const prop of node.props) {
    if (prop.type === NodeTypes.ATTRIBUTE) {
      staticAttrs.push(prop)
    } else if (prop.type === NodeTypes.DIRECTIVE) {
      dynamicAttrs.push(prop)
    }
  }
  
  // 合并静态属性
  if (staticAttrs.length > 0) {
    const mergedAttrs = mergeStaticAttributes(staticAttrs)
    node.props = [mergedAttrs, ...dynamicAttrs]
  }
  
  // 优化动态属性
  for (const prop of dynamicAttrs) {
    if (prop.name === 'bind' && prop.arg?.isStatic) {
      // 内联简单的动态属性
      if (isInlineableBinding(prop.exp)) {
        prop.exp.content = inlineBindingExpression(prop.exp)
      }
    }
  }
}

7.2 运行时性能优化

内存优化与垃圾回收

// 对象池管理
class VNodePool {
  private pool: VNode[] = []
  private size = 0
  private maxSize = 1000
  
  acquire(tag: string, props: any, children: any): VNode {
    if (this.size > 0) {
      this.size--
      const vnode = this.pool.pop()!
      
      // 复用vnode
      vnode.tag = tag
      vnode.props = props
      vnode.children = children
      vnode.el = null
      vnode.component = null
      vnode.shapeFlag = getShapeFlag(tag, children)
      
      return vnode
    }
    
    // 创建新的vnode
    return createVNode(tag, props, children)
  }
  
  release(vnode: VNode) {
    if (this.size < this.maxSize) {
      // 清理引用
      vnode.el = null
      vnode.component = null
      vnode.ctx = null
      vnode.suspense = null
      vnode.ssContent = null
      vnode.ssFallback = null
      vnode.transition = null
      
      this.pool.push(vnode)
      this.size++
    }
  }
  
  clear() {
    this.pool.length = 0
    this.size = 0
  }
}

// 响应式对象缓存
class ReactiveCache {
  private cache = new WeakMap<object, any>()
  private proxyCache = new WeakMap<object, any>()
  
  getReactive(target: object): any {
    let reactive = this.cache.get(target)
    if (!reactive) {
      reactive = reactive(target)
      this.cache.set(target, reactive)
    }
    return reactive
  }
  
  getProxy(target: object, handler: ProxyHandler<any>): any {
    let proxy = this.proxyCache.get(target)
    if (!proxy) {
      proxy = new Proxy(target, handler)
      this.proxyCache.set(target, proxy)
    }
    return proxy
  }
  
  clear() {
    // 清空缓存
    this.cache = new WeakMap()
    this.proxyCache = new WeakMap()
  }
}

// 批量更新优化
class BatchUpdater {
  private updates: (() => void)[] = []
  private scheduled = false
  
  schedule(update: () => void) {
    this.updates.push(update)
    
    if (!this.scheduled) {
      this.scheduled = true
      
      // 在微任务中批量执行
      Promise.resolve().then(() => {
        this.flush()
      })
    }
  }
  
  flush() {
    const updates = this.updates.slice()
    this.updates.length = 0
    this.scheduled = false
    
    // 批量执行更新
    for (const update of updates) {
      try {
        update()
      } catch (error) {
        console.error('批量更新错误:', error)
      }
    }
  }
  
  cancel() {
    this.updates.length = 0
    this.scheduled = false
  }
}

虚拟DOM复用策略

// VNode复用策略
interface VNodeReuseStrategy {
  canReuse(n1: VNode, n2: VNode): boolean
  reuse(n1: VNode, n2: VNode): void
}

// 默认复用策略
const defaultReuseStrategy: VNodeReuseStrategy = {
  canReuse(n1: VNode, n2: VNode): boolean {
    // 检查类型是否相同
    if (n1.type !== n2.type) {
      return false
    }
    
    // 检查key是否相同
    if (n1.key !== n2.key) {
      return false
    }
    
    // 检查props是否兼容
    if (!arePropsCompatible(n1.props, n2.props)) {
      return false
    }
    
    // 检查子节点是否兼容
    if (!areChildrenCompatible(n1.children, n2.children)) {
      return false
    }
    
    return true
  },
  
  reuse(n1: VNode, n2: VNode): void {
    // 复用el引用
    n2.el = n1.el
    
    // 复用组件实例
    if (n1.component) {
      n2.component = n1.component
    }
    
    // 复用transition状态
    if (n1.transition) {
      n2.transition = n1.transition
    }
    
    // 标记为复用
    n2.reused = true
  }
}

// 应用复用策略
function tryReuseVNode(
  n1: VNode | null,
  n2: VNode,
  strategy: VNodeReuseStrategy = defaultReuseStrategy
): boolean {
  if (n1 && strategy.canReuse(n1, n2)) {
    strategy.reuse(n1, n2)
    return true
  }
  
  return false
}

// 组件级别的复用
function reuseComponent(
  n1: VNode,
  n2: VNode,
  parentComponent: ComponentInternalInstance | null,
  parentSuspense: SuspenseBoundary | null
): boolean {
  const instance = n1.component!
  
  // 检查props是否变化
  const { props: nextProps } = n2
  const { props: prevProps } = n1
  
  if (hasPropsChanged(prevProps, nextProps)) {
    // props变化,需要更新
    instance.next = n2
    instance.update()
    return false
  }
  
  // 复用组件实例
  n2.component = instance
  n2.el = n1.el
  
  // 更新vnode引用
  instance.vnode = n2
  
  // 标记组件为复用
  instance.isReused = true
  
  return true
}

第八章:TypeScript类型系统与类型安全

8.1 响应式类型系统

// 基础类型定义
type Primitive = string | number | boolean | bigint | symbol | undefined | null
type Builtin = Primitive | Function | Date | Error | RegExp

// 响应式类型映射
type UnwrapNestedRefs<T> = T extends Ref ? T : UnwrapRef<T>

type UnwrapRef<T> = T extends Ref<infer V>
  ? UnwrapRefSimple<V>
  : UnwrapRefSimple<T>

type UnwrapRefSimple<T> = T extends
  | Function
  | CollectionTypes
  | BaseTypes
  | Ref
  | RefUnion
  ? T
  : T extends Array<any>
  ? { [K in keyof T]: UnwrapRefSimple<T[K]> }
  : T extends object
  ? {
      [P in keyof T]: P extends symbol ? T[P] : UnwrapRef<T[P]>
    }
  : T

// Ref类型
interface Ref<T = any> {
  value: T
  /**
   * Type differentiator only.
   * We need this to be in public d.ts but don't want it to show up in IDE
   * autocomplete, so we use a private Symbol instead.
   */
  [RefSymbol]: true
  /**
   * @internal
   */
  _shallow?: boolean
}

// Reactive类型
type Reactive<T> = UnwrapNestedRefs<T>

// Computed类型
interface ComputedRef<T = any> extends WritableComputedRef<T> {
  readonly value: T
  [ComputedRefSymbol]: true
}

interface WritableComputedRef<T> extends Ref<T> {
  readonly effect: ReactiveEffect<T>
}

// 工具类型
type MaybeRef<T> = T | Ref<T>
type MaybeRefOrGetter<T> = MaybeRef<T> | (() => T)

// 响应式函数类型
function reactive<T extends object>(target: T): Reactive<T>
function ref<T>(value: T): Ref<UnwrapRef<T>>
function ref<T = any>(): Ref<T | undefined>
function computed<T>(
  getter: () => T,
  debugOptions?: DebuggerOptions
): ComputedRef<T>
function computed<T>(
  options: {
    get: () => T
    set: (value: T) => void
  },
  debugOptions?: DebuggerOptions
): WritableComputedRef<T>

// 组件Props类型推导
type ExtractPropTypes<O> = O extends object
  ? { [K in RequiredKeys<O>]: InferPropType<O[K]> } &
      { [K in OptionalKeys<O>]?: InferPropType<O[K]> }
  : { [key: string]: any }

type RequiredKeys<T> = {
  [K in keyof T]: T[K] extends
    | { required: true }
    | { default: any }
    | BooleanConstructor
    | { type: BooleanConstructor }
    ? T[K] extends { default: undefined | (() => undefined) }
      ? never
      : K
    : never
}[keyof T]

type OptionalKeys<T> = Exclude<keyof T, RequiredKeys<T>>

type InferPropType<T> = T extends null
  ? any // null & true would fail to infer
  : T extends { type: null | true }
  ? any // As TS issue https://github.com/Microsoft/TypeScript/issues/14829
  : T extends ObjectConstructor | { type: ObjectConstructor }
  ? Record<string, any>
  : T extends BooleanConstructor | { type: BooleanConstructor }
  ? boolean
  : T extends DateConstructor | { type: DateConstructor }
  ? Date
  : T extends Prop<infer V>
  ? V
  : T extends ArrayConstructor | { type: ArrayConstructor }
  ? any[]
  : T extends PropOptions<infer V>
  ? V
  : T extends Constructor
  ? InstanceType<T>
  : T

8.2 组件类型推导

// 组件选项类型
interface ComponentOptions<
  Props = {},
  RawBindings = {},
  D = {},
  C extends ComputedOptions = {},
  M extends MethodOptions = {},
  Mixin extends ComponentOptionsMixin = ComponentOptionsMixin,
  Extends extends ComponentOptionsMixin = ComponentOptionsMixin,
  E extends EmitsOptions = {},
  S extends string = string,
  EE extends string = string
> {
  // 状态
  data?: (this: CreateComponentPublicInstance<Props, RawBindings>) => D
  computed?: C
  methods?: M
  
  // 生命周期
  beforeCreate?: (this: CreateComponentPublicInstance<Props, RawBindings>) => void
  created?: (this: CreateComponentPublicInstance<Props, RawBindings>) => void
  beforeMount?: (this: CreateComponentPublicInstance<Props, RawBindings>) => void
  mounted?: (this: CreateComponentPublicInstance<Props, RawBindings>) => void
  beforeUpdate?: (this: CreateComponentPublicInstance<Props, RawBindings>) => void
  updated?: (this: CreateComponentPublicInstance<Props, RawBindings>) => void
  beforeUnmount?: (this: CreateComponentPublicInstance<Props, RawBindings>) => void
  unmounted?: (this: CreateComponentPublicInstance<Props, RawBindings>) => void
  errorCaptured?: ErrorCapturedHook
  
  // 渲染
  render?: (ctx: CreateComponentPublicInstance<Props, RawBindings>) => VNodeChild
  template?: string
  
  // Props
  props?: (PropsOptions<Props> | Array<keyof Props>)
  
  // Emits
  emits?: (E | Array<EE>) | EmitsOptions
  
  // 暴露
  expose?: string[]
  
  // 继承
  mixins?: Mixin[]
  extends?: Extends
  
  // 自定义
  [key: string]: any
}

// Setup上下文类型
interface SetupContext<
  E extends EmitsOptions = {},
  S extends SlotsType = {},
  EE extends string = string
> {
  attrs: Data
  slots: UnwrapSlotsType<S>
  emit: EmitFn<E, EE>
  expose: (exposed?: Record<string, any>) => void
}

// 组合式函数类型
type UseFetchReturn<T> = {
  data: Ref<T | null>
  error: Ref<Error | null>
  loading: Ref<boolean>
  execute: () => Promise<void>
}

function useFetch<T>(url: MaybeRef<string>): UseFetchReturn<T>
function useFetch<T>(url: MaybeRef<string>, options: UseFetchOptions): UseFetchReturn<T>

// 自定义指令类型
type DirectiveHook<T = any, Prev = VNode<any, T> | null, V = any> = (
  el: T,
  binding: DirectiveBinding<V>,
  vnode: VNode<any, T>,
  prevVNode: Prev
) => void

interface DirectiveBinding<V = any> {
  instance: ComponentPublicInstance | null
  value: V
  oldValue: V | null
  arg?: string
  modifiers: DirectiveModifiers
  dir: ObjectDirective<any, V>
}

type DirectiveArguments<
  Name extends string,
  Modifiers extends string = string
> = [
  name: Name,
  value?: any,
  modifiers?: Partial<Record<Modifiers, boolean>>
]

总结与展望

Vue 3 是一个工程学上的杰作,它在保持易用性的同时,通过精妙的设计实现了性能和开发体验的显著提升。通过本文的深度解析,我们可以总结出 Vue 3 的核心优势:

核心优势总结

  1. 性能飞跃:基于 Proxy 的响应式系统、编译时优化、虚拟 DOM Diff 算法优化等,使得性能相比 Vue 2 有 2-3 倍的提升。

  2. 组合式 API:更灵活的逻辑复用、更好的 TypeScript 支持、更清晰的逻辑组织。

  3. 更好的 TypeScript 支持:完整的类型推导、更严格的类型检查、更好的 IDE 支持。

  4. 更小的体积:Tree-shaking 支持、模块化设计,使得生产包体积更小。

  5. 更好的可维护性:清晰的模块边界、更好的代码组织、更完善的错误处理。

学习建议

  1. 深入理解响应式原理:这是 Vue 3 的核心,理解 Proxy、依赖收集、派发更新的机制。

  2. 掌握编译时优化:了解静态提升、Patch Flags、树结构压平等优化技术。

  3. 实践 Composition API:通过实际项目练习,掌握逻辑复用的最佳实践。

  4. 阅读源码:选择感兴趣的部分深入阅读,理解实现细节。

  5. 关注生态发展:Vue 3 的生态还在快速发展,关注新的工具和库。

未来展望

Vue 3 不仅是一个框架的升级,更是前端开发理念的进化。随着 Vue 3 生态的不断完善,我们有理由相信:

  1. 更多编译时优化:静态分析、代码生成优化等将持续改进。

  2. 更好的开发体验:Vite 等工具将进一步提升开发效率。

  3. 更丰富的生态:更多的组件库、工具链将支持 Vue 3。

  4. 更广泛的应用:从 Web 到桌面、移动端,Vue 3 的应用场景将更加广泛。

Vue 3 的成功在于它平衡了易用性、性能和可维护性,这为前端开发提供了一个优秀的范例。无论你是 Vue 新手还是资深开发者,深入理解 Vue 3 都将对你的技术成长大有裨益。


vue3详解
http://localhost:8090/archives/vue3xiang-jie
作者
Administrator
发布于
2026年02月10日
许可协议