亲宝软件园·资讯

展开

Vue ParseHTML函数模板

MiyueFE 人气:0

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) {
  }
}

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

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

加载全部内容

相关教程
猜你喜欢
用户评论