千家信息网

vue模版编译的示例分析

发表于:2025-02-02 作者:千家信息网编辑
千家信息网最后更新 2025年02月02日,这篇文章给大家分享的是有关vue模版编译的示例分析的内容。小编觉得挺实用的,因此分享给大家做个参考,一起跟随小编过来看看吧。思考:html是标签语言,只有JS才能实现判断、循环,而模版有指令、插值、J
千家信息网最后更新 2025年02月02日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安全错误 数据库的锁怎样保障安全 高德网络安全专家刘忠耀 连云港车路协同服务器 化学数据分析软件开发 国外软件开发工资一般多少钱 应届生网络安全员待遇 dna数据库 入吗 数据库 所有者 2020年深圳网络安全大赛 数据库情景分析题 杭州网络技术研究所 软件开发工具与环境考试题 手机软件开发备忘录 用来学软件开发电脑配置 闵行区推广软件开发哪家好 计算机网络技术好学吗在技校 什么是网络安全防护措施 东南大学了网络安全 佛山地产软件开发定制 网络技术的使用成本 智能互联网科技 非肿瘤m6a数据库 数据库左连接 右连接查询 qq空间关了怎么清空数据库 抽奖数据库设计 网络技术方面怎么考证 天下捷融互联网科技小贷利率 随着网络技术的发展在线教育 电站网络安全检查 北京理工大学空间网络安全学院 呼和浩特市回民区网络安全电话
    0