龙空技术网

Vue源码全面解析三十 parseHTML函数(解析html(一)开始标签)

小小的码农 174

前言:

现在大家对“parsehtml”大致比较重视,小伙伴们都想要剖析一些“parsehtml”的相关知识。那么小编在网上收集了一些对于“parsehtml””的相关文章,希望兄弟们能喜欢,小伙伴们一起来学习一下吧!

由于parseHTML函数代码实在过于庞大,我这里就不一次性贴出源代码了,大家可以前往()查看源代码。

我们来总结一下该函数的主要功能:

1、匹配标签的 "<" 字符

匹配的标签名称不能是:script、style、textarea

有如下情况:

1、注释标签 /^<!\--/

2、条件注释 /^<!\[/

3、html文档头部 /^<!DOCTYPE [^>]+>/i

4、标签结束 /^<\/ 开头

5、标签开始 /^</ 开头

然后开始匹配标签的属性包括w3的标准属性(id、class)或者自定义的任何属性,以及vue的指令(v-、:、@)等,直到匹配到 "/>" 标签的结尾。然后把已匹配的从字符串中删除,一直 while 循环匹配。

解析开始标签函数代码:

function parseStartTag () {   // 标签的开始 如<div    const start = html.match(startTagOpen)    if (start) {      const match = {        tagName: start[1], // 标签名称        attrs: [], // 标签属性        start: index // 开始位置      }       // 减去已匹配的长度      advance(start[0].length)      let end, attr      while (!(end = html.match(startTagClose)) && (attr = html.match(dynamicArgAttribute) || html.match(attribute))) {        attr.start = index        v        advance(attr[0].length)          attr.end = index        match.attrs.push(attr) // 把匹配到的属性添加到attrs数组      }      if (end) { // 标签的结束符 ">"        match.unarySlash = end[1]        advance(end[0].length)  // 减去已匹配的长度        match.end = index  // 结束位置        return match      }    }  }

处理过后结构如下:

接下来就是处理组合属性,调用 “handleStartTag” 函数

 function handleStartTag (match) {    const tagName = match.tagName // 标签名称    const unarySlash = match.unarySlash // 一元标签    if (expectHTML) {      if (lastTag === 'p' && isNonPhrasingTag(tagName)) {        // 解析标签结束        parseEndTag(lastTag)      }      if (canBeLeftOpenTag(tagName) && lastTag === tagName) {        parseEndTag(tagName)      }    }   // 是否为一元标签    const unary = isUnaryTag(tagName) || !!unarySlash    const l = match.attrs.length    // 标签属性集合    const attrs = new Array(l)    for (let i = 0; i < l; i++) {      const args = match.attrs[i]      const value = args[3] || args[4] || args[5] || ''      const shouldDecodeNewlines = tagName === 'a' && args[1] === 'href' ? options.shouldDecodeNewlinesForHref : options.shouldDecodeNewlines      attrs[i] = {        name: args[1], // 属性名称        value: decodeAttr(value, shouldDecodeNewlines) // 属性值      }      if (process.env.NODE_ENV !== 'production' && options.outputSourceRange) {        // 开始位置        attrs[i].start = args.start + args[0].match(/^\s*/).length        // 结束位置        attrs[i].end = args.end      }    }    if (!unary) {      stack.push({ tag: tagName, lowerCasedTag: tagName.toLowerCase(), attrs: attrs, start: match.start, end: match.end })      lastTag = tagName    }		// 调用start函数    if (options.start) {      options.start(tagName, attrs, unary, match.start, match.end)    }  }

我们简单说一下最后调用的start函数的作用:

1、判断是否为svg标签,并处理svg在ie下的兼容性问题

2、遍历标签属性,验证其名称是否有效

3、标签名是否为 style 或者 script ,如果在服务端会提示warn警告

4、检查属性是否存在 v-for、v-if、v-once指令

5、如果是更元素就验证其合法性,不能是 slot 和 template 标签,不能存在 v-for指令

以上就是界面html模板的开始标签的分析,接下来我们来分析如何匹配结束标签。

请看:Vue源码全面解析三十 parseHTML函数(解析html(二)结束标签)

如有错误,欢迎指正,谢谢。

标签: #parsehtml