当前位置:首页 > VUE

vue compile源码实现

2026-01-16 08:16:13VUE

Vue 的模板编译(compile)是将模板字符串转换为渲染函数的过程,涉及解析、优化和代码生成三个阶段。以下是其核心实现原理的分析:

解析阶段(Parse)

将模板字符串转换为抽象语法树(AST),主要通过正则表达式和字符串处理完成。

模板解析示例

<div id="app">{{ message }}</div>

会被解析为类似以下的 AST 结构:

{
  type: 1, // 元素节点
  tag: 'div',
  attrsList: [{ name: 'id', value: 'app' }],
  children: [{
    type: 2, // 文本节点
    expression: '_s(message)',
    text: '{{ message }}'
  }]
}

关键代码

// src/compiler/parser/index.js
export function parse(template, options) {
  const stack = []
  let root
  let currentParent
  parseHTML(template, {
    start(tag, attrs) {
      // 处理开始标签
      const element = createASTElement(tag, attrs)
      if (!root) root = element
      if (currentParent) currentParent.children.push(element)
      stack.push(element)
      currentParent = element
    },
    end() {
      // 处理结束标签
      stack.pop()
      currentParent = stack[stack.length - 1]
    },
    chars(text) {
      // 处理文本
      if (currentParent) currentParent.children.push({ type: 3, text })
    }
  })
  return root
}

优化阶段(Optimize)

标记静态节点和静态根节点,避免在重新渲染时重复处理。

静态节点标记

  • 通过 markStatic 递归遍历 AST,标记所有静态节点(无动态绑定或指令)。
  • 静态根节点是子节点全为静态的父节点。

关键代码

// src/compiler/optimizer.js
export function optimize(root) {
  markStatic(root)
  markStaticRoots(root)
}

function markStatic(node) {
  node.static = isStatic(node)
  if (node.type === 1) {
    node.children.forEach(child => {
      markStatic(child)
      if (!child.static) node.static = false
    })
  }
}

代码生成阶段(Generate)

将 AST 转换为可执行的渲染函数字符串。

代码生成示例: 对于 AST:

{
  tag: 'div',
  attrs: [{ name: 'id', value: '"app"' }],
  children: [{ type: 2, expression: '_s(message)', text: '{{ message }}' }]
}

生成的渲染函数代码:

with(this) {
  return _c('div', { attrs: { id: "app" } }, [_v(_s(message))])
}

关键代码

// src/compiler/codegen/index.js
export function generate(ast) {
  const code = ast ? genElement(ast) : '_c("div")'
  return `with(this){return ${code}}`
}

function genElement(el) {
  const children = genChildren(el)
  const data = genData(el)
  return `_c('${el.tag}'${data ? `,${data}` : ''}${children ? `,${children}` : ''})`
}

核心工具函数

  1. _c: 创建虚拟 DOM 节点(createElement)。
  2. _v: 创建文本节点(createTextVNode)。
  3. _s: 转换为字符串(toString)。
// src/core/instance/render-helpers/index.js
export function installRenderHelpers(target) {
  target._c = createElement
  target._v = createTextVNode
  target._s = toString
}

编译入口

通过 createCompiler 整合三个阶段:

// src/compiler/index.js
export const createCompiler = createCompilerCreator(function baseCompile(template, options) {
  const ast = parse(template.trim(), options)
  optimize(ast, options)
  const code = generate(ast, options)
  return { ast, render: code }
})

最终生成的渲染函数可通过 new Function 实例化,供组件渲染使用。

vue compile源码实现

标签: 源码vue
分享给朋友:

相关文章

vue循环数组实现

vue循环数组实现

vue循环数组的实现方法 在Vue中循环数组主要通过v-for指令实现,以下是几种常见用法: 基本数组循环 使用v-for指令遍历数组,可以通过(item, index)的语法获取当前项和索引值:…

vue实现网页切换

vue实现网页切换

Vue 实现网页切换的方法 在 Vue 中实现网页切换通常可以通过以下几种方式完成,具体取决于项目需求和路由管理方式。 使用 Vue Router Vue Router 是 Vue.js 官方提供…

vue实现tab换行

vue实现tab换行

Vue实现Tab切换的常见方法 使用Vue实现Tab切换功能可以通过多种方式完成,以下是几种常见的方法: 动态组件结合v-if或v-show 通过v-if或v-show控制不同Tab内容的显示…

拖拽式编程vue实现

拖拽式编程vue实现

拖拽式编程在 Vue 中的实现方法 使用 HTML5 原生拖放 API Vue 可以结合 HTML5 的拖放 API 实现基础拖拽功能。通过 draggable 属性标记可拖拽元素,监听 dragst…

vue实现文字播放栏

vue实现文字播放栏

Vue 实现文字播放栏(跑马灯效果) 方法一:使用 CSS 动画 + Vue 数据绑定 通过 CSS 的 @keyframes 实现动画效果,结合 Vue 的动态数据绑定控制内容。 <t…

vue登录业务的实现

vue登录业务的实现

实现登录业务的基本流程 在Vue中实现登录业务通常涉及前端界面设计、表单验证、API请求交互、状态管理以及路由控制等环节。以下是核心实现步骤: 登录表单设计与验证 创建包含用户名和密码输入框的登录…