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

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

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

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

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

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

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

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

Vue2 源码解析

响应式原理

Object.defineProperty

function defineReactive(obj, key, val) {
  const dep = new Dep()
  
  Object.defineProperty(obj, key, {
    enumerable: true,
    configurable: true,
    get() {
      if (Dep.target) {
        dep.depend()
      }
      return val
    },
    set(newVal) {
      if (newVal === val) return
      val = newVal
      dep.notify()
    }
  })
}

依赖收集

class Dep {
  constructor() {
    this.subs = []
  }
  
  addSub(sub) {
    this.subs.push(sub)
  }
  
  depend() {
    if (Dep.target) {
      Dep.target.addDep(this)
    }
  }
  
  notify() {
    this.subs.forEach(sub => sub.update())
  }
}

Watcher

class Watcher {
  constructor(vm, expOrFn, cb) {
    this.vm = vm
    this.cb = cb
    this.getter = expOrFn
    this.value = this.get()
  }
  
  get() {
    Dep.target = this
    const value = this.getter.call(this.vm, this.vm)
    Dep.target = null
    return value
  }
  
  update() {
    const oldValue = this.value
    this.value = this.get()
    this.cb.call(this.vm, this.value, oldValue)
  }
}

虚拟 DOM

VNode 结构

class VNode {
  constructor(tag, data, children, text, elm) {
    this.tag = tag
    this.data = data
    this.children = children
    this.text = text
    this.elm = elm
    this.key = data && data.key
  }
}

Diff 算法

function patch(oldVnode, vnode) {
  if (sameVnode(oldVnode, vnode)) {
    patchVnode(oldVnode, vnode)
  } else {
    const elm = oldVnode.elm
    const parent = elm.parentNode
    createElm(vnode)
    parent.insertBefore(vnode.elm, elm)
    parent.removeChild(elm)
  }
}

function patchVnode(oldVnode, vnode) {
  const elm = vnode.elm = oldVnode.elm
  const oldCh = oldVnode.children
  const ch = vnode.children
  
  if (oldVnode === vnode) return
  
  if (vnode.text) {
    elm.textContent = vnode.text
  } else {
    if (oldCh && ch) {
      updateChildren(elm, oldCh, ch)
    }
  }
}
最近更新: 2026/1/27 15:51
Contributors: hailong
Prev
Vue2 服务端渲染(SSR)