当前位置:首页 > 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 整合三个阶段:

vue compile源码实现

// 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
分享给朋友:

相关文章

vue课程实现

vue课程实现

Vue 课程实现方案 课程内容设计 Vue课程应从基础到高级逐步展开,涵盖Vue核心概念、组件化开发、状态管理、路由、构建工具等。基础部分包括Vue实例、模板语法、计算属性和侦听器。中级部分深入组件通…

vue实现弹幕

vue实现弹幕

Vue 实现弹幕功能 弹幕功能通常包括动态生成、滚动显示、颜色和速度随机化等特性。以下是基于 Vue 3 的实现方法。 核心思路 使用 CSS 动画控制弹幕从右向左滚动。 动态生成弹幕数据,随机设置…

vue 绑定实现

vue 绑定实现

Vue 绑定实现 Vue 提供了多种数据绑定的方式,包括文本插值、属性绑定、事件绑定、双向绑定等。以下是常见的绑定实现方法: 文本插值 使用双大括号 {{ }} 进行文本插值,将数据动态渲染到 DO…

vue实现抽屉

vue实现抽屉

Vue 实现抽屉组件 抽屉组件是一种常见的 UI 模式,通常用于从屏幕边缘滑出内容。以下是几种实现抽屉的方法: 使用 Vue 原生实现 创建一个基本的抽屉组件,利用 Vue 的过渡和条件渲染功能。…

vue博客实现

vue博客实现

Vue 博客实现步骤 项目初始化与基础配置 使用 Vue CLI 或 Vite 创建项目,安装基础依赖如 vue-router 和状态管理库(如 pinia)。配置路由文件实现页面跳转逻辑,例如博客首…

vue实现组件跟随

vue实现组件跟随

实现组件跟随的常见方法 使用CSS定位 通过CSS的position: fixed或position: absolute属性实现组件跟随。需要结合JavaScript计算目标元素的位置。 <t…