千家信息网

vue模版编译的示例分析

发表于:2025-11-11 作者:千家信息网编辑
千家信息网最后更新 2025年11月11日,这篇文章给大家分享的是有关vue模版编译的示例分析的内容。小编觉得挺实用的,因此分享给大家做个参考,一起跟随小编过来看看吧。思考:html是标签语言,只有JS才能实现判断、循环,而模版有指令、插值、J
千家信息网最后更新 2025年11月11日vue模版编译的示例分析

这篇文章给大家分享的是有关vue模版编译的示例分析的内容。小编觉得挺实用的,因此分享给大家做个参考,一起跟随小编过来看看吧。

思考:

html是标签语言,只有JS才能实现判断、循环,而模版有指令、插值、JS表达式,能够实现判断、循环等,故模板不是html,因此模板一定是转换为某种JS代码,这种编译又是如何进行的?

解析:

模版编译是将template编译成render函数的过程,这个过程大致可以分成三个阶段:

1、parse 解析器

解析器主要就是将 模板字符串 转换成 element ASTs

模板字符串:

{{message}}

element ASTs

AST是指抽象语法树 和 Vnode 类似,都是使用JavaScript对象来描述节点的树状表现形式

{  tag: "div"  // 节点的类型(1标签,2包含字面量表达式的文本节点,3普通文本节点或注释节点)  type: 1,  // 静态根节点  staticRoot: false,  // 静态节点  static: false,  plain: true,  // 父节点元素描述对象的引用  parent: undefined,  // 只有当节点类型为1,才会有attrsList属性,它是一个对象数组,存储着原始的html属性名和值  attrsList: [],  // 同上,区别是attrsMap是以键值对的方式保存html属性名和值的  attrsMap: {},  // 存储着该节点所有子节点的元素描述对象  children: [      {      tag: "p"      type: 1,      staticRoot: false,      static: false,      plain: true,      parent: {tag: "div", ...},      attrsList: [],      attrsMap: {},      children: [{          type: 2,          text: "{{message}}",          static: false,          // 当节点类型为2时,对象会包含的表达式          expression: "_s(message)"      }]    }  ]}

1.1 截取的规则

主要是通过判断模板中html.indexof('<')的值,来确定要截取标签还是文本.

截取的过程:

字符串部分

`

{{message}}

`

1.2 截取过程部分

第一次截取

  • 判断模板中html.indexof('<')的值, 为零 (注释、条件注释、doctype、开始标签、结束标签中的一种)

  • 被起始标签的正则匹配成功,获取当前的标签名为div,然后截掉匹配成功的'

    {{message}}

  • 截取掉开始标签后,会使用匹配属性的正则去匹配,如果匹配成功,则得到该标签的属性列表,如果匹配不成功,则该标签的属性列表为空数组

  • 截掉属性后,会使用匹配开始标签结束的正则去匹配,得到它是否是自闭合标签的信息,然后截掉匹配到的字符串得到新的字符串

    {{message}}


  • 匹配到开始标签,判断当前节点是否存在根节点,不存在则会创建一个元素类型的树节点,存在,则将其设置为currentParent的子节点,然后将当前节点压入stack栈中

  • /**   总结为,匹配标签,提取属性,建立层级*/// 经过上面的匹配,剩下的字符串部分为:`

    {{message}}

    `

    第二次截取

    /**    同上*/// 经过上面的匹配,剩下的字符串部分为:`{{message}}

    `

    第三次截取

    例如:

    a < b

    => 文本部分 a < b ,命中结束标签

    a => 文本部分 a
    ,命中开始标签

    /**   总结为,判断类型,截取文本*/// 经过上面的匹配,剩下的字符串部分为:`

    `

    第四次截取

    /**    总结为,匹配标签,确定层级*/// 经过上面的匹配,剩下的字符串部分为:``第五次截取/**    同上*/结束

    1.3 解析器总结

    2、optimize 优化器

    优化器的作用主要是对生成的AST进行静态内容的优化,标记静态节点,为了每次重新渲染,不需要为静态子树创建新节点,可以跳过虚拟DOM中patch过程(即不需要参与第二次的页面渲染了,大大提升了渲染效率)。

    2.1 静态节点

    遍历AST语法树,找出所有的静态节点并打上标记

    function isStatic (node) {    // expression    if (node.type === 2) {      return false    }    // text    if (node.type === 3) {      return true    }    /**

    1. 不能使用动态绑定语法,即标签上不能有v-、@、:开头的属性;
    2. 不能使用v-if、v-else、v-for指令;
    3. 不能是内置组件,即标签名不能是slotcomponent
    4. 标签名必须是平台保留标签,即不能是组件;
    5. 当前节点的父节点不能是带有 v-fortemplate 标签;
    6. 节点的所有属性的 key 都必须是静态节点才有的 key,注:静态节点的key是有限的,

    它只能是type,tag,attrsList,attrsMap,plain,parent,children,attrs之一;

    */    return !!(node.pre || (      !node.hasBindings &&      !node.if && !node.for &&      !isBuiltInTag(node.tag) &&      isPlatformReservedTag(node.tag) &&      !isDirectChildOfTemplateFor(node) &&      Object.keys(node).every(isStaticKey)    ))}

    2.2 静态根节点

    遍历经过上面步骤后的树,找出静态根节点,并打上标记

    2.3 优化器总结

    3、generate 代码生成器

    代码生成器的作用是通过AST语法树生成代码字符串,代码字符串被包装进渲染函数,执行渲染函数后,可以得到一份vnode

    3.1 JS的with语法

    使用 with,能改变{}内自由变量的查找方式,将{}内自由变量,当做 obj 的属性来查找,如果找不到匹配的obj属性,就会报错

    const obj = {a: 100, b: 200}with(obj) {     console.log(a)     console.log(b)     // console.log(c) // 会报错}

    代码字符串

    解析parse生成的element ASTs,拼接成字符串

    with(this){return _c('div',_c('p',[_v(message)])])}

    得到render函数:

    /** 代码字符串通过new Function('代码字符串')就可以得到当前组件的render函数 */const stringCode = `with(this){return _c('div',_c('p',[_v(message)])])}`const render = new Function(stringCode)

    欲观看不同指令、插值、JS表达式,可使用vue-template转换

    const compiler = require('vue-template-compiler')// 插值const template = `

    {{message}}

    `const result = compiler.compile(template)console.log(result.render)// with(this){return _c('p',[_v(_s(message))])}

    vue 源代码找到缩写函数的含义

    模板编译的源码可以在 `vue-template-compiler` [2] 包中查看

    function installRenderHelpers(target) {    target._c = createElement    // 标记v-once    target._o = markOnce    // 转换成Number类型    target._n = toNumber    // 转换成字符串    target._s = toString    // 渲染v-for    target._l = renderList    // 渲染普通插槽和作用域插槽    target._t = renderSlot    // 通过staticRenderFns渲染静态节点    target._m = renderStatic    // 获取过滤器    target._f = resolveFilter    // 检查键盘事件keycode    target._k = checkKeyCodes    target._b = bindObjectProps    // 创建文本vnode    target._v = createTextVNode    // 创建空vnode    target._e = createEmptyVNode    target._u = resolveScopedSlots    target._g = bindObjectListeners    // 处理修饰符    target._p = prependModifier}

    感谢各位的阅读!关于"vue模版编译的示例分析"这篇文章就分享到这里了,希望以上内容可以对大家有一定的帮助,让大家可以学到更多知识,如果觉得文章不错,可以把它分享出去让更多的人看到吧!

    很赞哦!
    节点 标签 字符 字符串 静态 属性 模板 成功 代码 文本 注释 过程 编译 函数 类型 语法 元素 对象 表达式 部分 数据库的安全要保护哪些东西 数据库安全各自的含义是什么 生产安全数据库录入 数据库的安全性及管理 数据库安全策略包含哪些 海淀数据库安全审计系统 建立农村房屋安全信息数据库 易用的数据库客户端支持安全管理 连接数据库失败ssl安全错误 数据库的锁怎样保障安全 免费数据库修复软件 个人信用数据库标准 开发软件什么时候可以连接数据库 无极通网络技术 视频监控系统的管理服务器 如何进入穿越火线服务器 运维服务器监控 网络安全服务工程师简历 南方电网网络安全专业怎么样 网络安全宣传漫画图片简单 每搜网络技术有限公司年会 南邮 数据库 中级软件开发工资 数据库系统比数据库大么 绵阳互联网科技 mis软件开发平台好吗 服务器被挖矿的经历 济南聚量网络技术是做什么的 适用于服务器的安全软件 医学专业的软件开发 网络安全法培训 烟草 华为服务器设置管理地址 服务器ddr4 品牌 君达智尚网络技术 虚拟化底层服务器 网络安全 经费 hr软件开发工具 水利网络安全顶层设计 我国做服务器上市公司 考勤机丢失数据库
    0