Vue 2源码解析ParseHTML函数HTML模板

 更新时间:2022年08月15日 11:04:15   作者:MiyueFE  
这篇文章主要为大家介绍了Vue 2源码解析ParseHTML函数HTML模板详解,有需要的朋友可以借鉴参考下,希望能够有所帮助,祝大家多多进步,早日升职加薪

ParseHTML函数 - HTML 模板解析

之前在解析 parse 函数时,我们知道整个 解析 template 模板并生成 ast 对象 的过程都发生在这个函数的执行过程中。

但是 parse 函数内部本身只定义了一些标签、指令的处理方法和警告函数,并且在传递给 parseHTML 函数的参数中定义了四个处理方法。

最终是通过调用 parseHTML 来解析 template 模板

整个解析过程,其实就是 通过一系列正则表达式来匹配 template 模板字符串,并截取该部分匹配内容并重新匹配剩余部分,直到全部匹配完成。

所有的正则表达式包含以下内容:

const attribute = /^\s*([^\s"'<>\/=]+)(?:\s*(=)\s*(?:"([^"]*)"+|'([^']*)'+|([^\s"'=<>`]+)))?/  // 静态属性解析
const dynamicArgAttribute = /^\s*((?:v-[\w-]+:|@|:|#)\[[^=]+?\][^\s"'<>\/=]*)(?:\s*(=)\s*(?:"([^"]*)"+|'([^']*)'+|([^\s"'=<>`]+)))?/ // 动态属性解析(含有 v-xxx:, :, @, # 的属性)
const ncname = `[a-zA-Z_][\\-\\.0-9_a-zA-Z${unicodeRegExp.source}]*`
const qnameCapture = `((?:${ncname}\\:)?${ncname})`
const startTagOpen = new RegExp(`^<${qnameCapture}`)   // 开始标签部分
const startTagClose = /^\s*(\/?)>/                     // 开始标签结束
const endTag = new RegExp(`^<\\/${qnameCapture}[^>]*>`)// 结束标签部分
const doctype = /^<!DOCTYPE [^>]+>/i                   // DOCTYPE 声明
const comment = /^<!\--/                               // 注释部分
const conditionalComment = /^<!\[/                     // 条件注释

parseHTML 的简要代码如下:

export function parseHTML(html, options: HTMLParserOptions) {
  const stack: any[] = []
  const expectHTML = options.expectHTML
  const isUnaryTag = options.isUnaryTag || no
  const canBeLeftOpenTag = options.canBeLeftOpenTag || no
  let index = 0
  let last, lastTag
  while (html) {
    last = html
    if (!lastTag || !isPlainTextElement(lastTag)) {
      let textEnd = html.indexOf('<')
      if (textEnd === 0) {
        if (comment.test(html)) {
          // 处理 注释
          advance()
          continue
        }
        if (conditionalComment.test(html)) {
          // 处理 条件注释
          advance()
          continue
        }
        // Doctype:
        if (html.match(doctype)) {
          advance()
          continue
        }
        // 结束:
        if (html.match(endTag)) {
          advance()
          parseEndTag()
          continue
        }
        // 开始:
        if (parseStartTag()) {
          advance()
          handleStartTag()
          continue
        }
      }
      // 处理纯文本
      options.chars()
      advance()
    } else {
      // 结束
      parseEndTag()
    }
    if (html === last) {
      options.chars && options.chars(html)
      break
    }
  }
  parseEndTag()
  function advance(n) {
  }
  function parseStartTag() {
  }
  function handleStartTag(match) {
  }
  function parseEndTag(tagName?: any, start?: any, end?: any) {
  }
}

其中定义了三个标签处理方法和一个定位方法:

  • advance 方法是更新当前解析到的文本位置 index,并截取掉已解析的部分
  • parseStartTag 方法用来解析标签的开始部分,内部会生成一个包含标签名 tagName 和属性数组 attrs 的对象 math,并循环解析内部的字符串直到解析完整个字符串,将解析到的属性存放到 attrs 数组中
  • handleStartTag 则是处理 parseStartTag 得到的 math 对象(大部分是处理每个属性),如果上面解析到是非闭合标签的话,也会将这个 math 对象修改成一个新对象插入到 parseHTML 执行时定义的 stack 元素栈中;当然,如果是自闭合标签,还会调用 parseEndTag 方法处理;并在 最后调用 options 中定义的 start 函数来生成 ast 对象
  • parseEndTag 方法就用来处理标签结束后的逻辑,会根据条件清除 stack 栈中的元素;如果此时元素标签是 br 或者 p,也会调用 option.start(),其他情况下一般会调用 options.end() 来结束当前标签的解析

总的来说,parseHTML 就是通过正则表达式来匹配不同的标签和属性,进行不同的标签/属性处理,最后通过 options 中的回调函数来创建完整的 ast 对象;并用 stack 元素栈的方式来保证原始 template 模板与 ast 对象的层级结构的一致性。

以上就是Vue 2源码解析ParseHTML函数HTML模板的详细内容,更多关于Vue ParseHTML函数模板的资料请关注脚本之家其它相关文章!

相关文章

  • axios无法加载响应数据:no data found for resource with given identifier报错解决

    axios无法加载响应数据:no data found for resource with given i

    最近在在做一个小查询功能的时候踩了一个坑,所以这篇文章主要给大家介绍了关于axios无法加载响应数据:no data found for resource with given identifier报错的解决方法,需要的朋友可以参考下
    2022-11-11
  • Vue3模板引用的操作方式示例详解

    Vue3模板引用的操作方式示例详解

    这篇文章主要为大家介绍了Vue3模板引用的操作方式示例详解,有需要的朋友可以借鉴参考下,希望能够有所帮助,祝大家多多进步,早日升职加薪
    2023-06-06
  • 详细聊聊vue中组件的props属性

    详细聊聊vue中组件的props属性

    父子组件之间的通信就是props down,events up,父组件通过属性props向下传递数据给子组件,子组件通过事件events 给父组件发送消息,这篇文章主要给大家介绍了关于vue中组件的props属性的相关资料,需要的朋友可以参考下
    2021-11-11
  • Vue实现导入Excel功能步骤详解

    Vue实现导入Excel功能步骤详解

    这篇文章主要介绍了Vue实现导入Excel功能,本文分步骤给大家介绍的非常详细,对大家的学习或工作具有一定的参考借鉴价值,需要的朋友可以参考下
    2021-07-07
  • VueJS如何引入css或者less文件的一些坑

    VueJS如何引入css或者less文件的一些坑

    本篇文章主要介绍了VueJS如何引入css或者less文件的一些坑,小编觉得挺不错的,现在分享给大家,也给大家做个参考。一起跟随小编过来看看吧
    2017-04-04
  • Vue中TypeScript和Pinia使用方法

    Vue中TypeScript和Pinia使用方法

    这篇文章主要介绍了Vue中TypeScript和Pinia使用方法,让我们来看一个简单的示例来演示TypeScript 和 Pinia的强大之处,需要的朋友可以参考下
    2023-07-07
  • Electron+vue3项目使用SQLite3数据库详细步骤(超详细)

    Electron+vue3项目使用SQLite3数据库详细步骤(超详细)

    Electron是一个基于vue.js的新框架,它可以构建桌面应用,这篇文章主要给大家介绍了关于Electron+vue3项目使用SQLite3数据库的详细步骤,文中通过代码介绍的非常详细,需要的朋友可以参考下
    2024-01-01
  • Vuejs第七篇之Vuejs过渡动画案例全面解析

    Vuejs第七篇之Vuejs过渡动画案例全面解析

    这篇文章主要介绍了Vuejs第七篇之Vuejs过渡动画案例全面解析的相关资料,需要的朋友可以参考下
    2016-09-09
  • js节流防抖应用场景,以及在vue中节流防抖的具体实现操作

    js节流防抖应用场景,以及在vue中节流防抖的具体实现操作

    这篇文章主要介绍了js节流防抖应用场景,以及在vue中节流防抖的具体实现操作,具有很好的参考价值,希望对大家有所帮助。一起跟随小编过来看看吧
    2020-09-09
  • vue2里面ref的具体使用方法

    vue2里面ref的具体使用方法

    本篇文章主要介绍了vue2里面ref的具体使用方法,小编觉得挺不错的,现在分享给大家,也给大家做个参考。一起跟随小编过来看看吧
    2017-10-10

最新评论