文章详情

短信预约-IT技能 免费直播动态提醒

请输入下面的图形验证码

提交验证

短信预约提醒成功

vue parseHTML 函数拿到返回值后的处理源码解析

2024-04-02 19:55

关注
目录

引言

继上篇文章:

parseHTML 函数源码解析

var startTagMatch = parseStartTag();
if (startTagMatch) {
	handleStartTag(startTagMatch);
	if (shouldIgnoreFirstNewline(startTagMatch.tagName, html)) {
		advance(1);
	}
	continue
}

在上个章节中知道startTagMatch 就是获取parseStartTag函数的返回值。并只有在成功匹配到开始标签的情况下parseStartTag 才会返回解析结果(一个对象),否则返回undefined。

假设有如下html(template)字符串:

<div id="box" v-if="watings"></div>

parseStartTag函数返回值

则parseStartTag函数的返回值如下:

match = {
  tagName: 'div',
  attrs: [
    [
      'id="box"',
      'id',
      '=',
      'box',
      undefined,
      undefined
    ],
    [
      ' v-if="watings"',
      'v-if',
      '=',
      'watings',
      undefined,
      undefined
    ]
  ],
  start: index,
  unarySlash: undefined,
  end: index
}

handleStartTag源码

现在我们假设匹配成功,那么if语句块中的代码将会被执行,此时会将解析结果作为参数传递给 handleStartTag 函数,handleStartTag源码如下:

function handleStartTag(match) {
	var tagName = match.tagName;
	var unarySlash = match.unarySlash;
	if (expectHTML) {
		if (lastTag === 'p' &amp;&amp; isNonPhrasingTag(tagName)) {
			parseEndTag(lastTag);
		}
		if (canBeLeftOpenTag$$1(tagName) &amp;&amp; lastTag === tagName) {
			parseEndTag(tagName);
		}
	}
	var unary = isUnaryTag$$1(tagName) || !!unarySlash;
	var l = match.attrs.length;
	var attrs = new Array(l);
	for (var i = 0; i &lt; l; i++) {
		var args = match.attrs[i];
		var value = args[3] || args[4] || args[5] || '';
		var shouldDecodeNewlines = tagName === 'a' &amp;&amp; args[1] === 'href' ?
			options.shouldDecodeNewlinesForHref :
			options.shouldDecodeNewlines;
		attrs[i] = {
			name: args[1],
			value: decodeAttr(value, shouldDecodeNewlines)
		};
	}
	if (!unary) {
		stack.push({
			tag: tagName,
			lowerCasedTag: tagName.toLowerCase(),
			attrs: attrs
		});
		lastTag = tagName;
	}
	if (options.start) {
		options.start(tagName, attrs, unary, match.start, match.end);
	}
}

tagName 及unarySlash

handleStartTag函数用来处理开始标签的解析结果,所以它接收parseStartTag函数的返回值作为参数。handleStartTag函数的一开始定义两个常量:tagName 以及 unarySlash:

var tagName = match.tagName;
var unarySlash = match.unarySlash;

根据上章节的内容就能理解,tagName 存储解析开始标签的标签名,unarySlash 可以根据他的值判断是解析的开始标签是否为一元标签。

接着是一个if语句块,if语句的判断条件是if (expectHTML),前面说过expectHTML 是parser选项,是一个布尔值,如果为真则该 if 语句块的代码将被执行。但是现在我们暂时不看这段代码,因为这段代码包含 parseEndTag 函数的调用,所以待我们讲解完 parseEndTag 函数之后,再回头来说这段代码。

在往下定义了三个变量:

var unary = isUnaryTag$$1(tagName) || !!unarySlash;
var l = match.attrs.length;
var attrs = new Array(l);

变量 unary 是一个布尔值,当它为真时代表着标签是一元标签,否则是二元标签。

他们通过isUnaryTag来判断,其原理通过传递的标签名判断是否有跟预设标准HTML中规定的那些一元标签一致。

l 和 attrs ,其中常量 l 的值存储着 match.attrs 数组的长度,而 attrs 常量则是一个与match.attrs数组长度相等的数组。

这两个常量将被用于接下来的for循环中:

for (var i = 0; i < l; i++) {
	var args = match.attrs[i];
	var value = args[3] || args[4] || args[5] || '';
	var shouldDecodeNewlines = tagName === 'a' && args[1] === 'href' ?
		options.shouldDecodeNewlinesForHref :
		options.shouldDecodeNewlines;
	attrs[i] = {
		name: args[1],
		value: decodeAttr(value, shouldDecodeNewlines)
	};
}

具体看一下循环体的代码,首先定义 args 常量,它的值就是每个属性的解析结果,即match.attrs 数组中的元素对象。

变量 value 中就保存着最终的属性值,如果第4、5、6 项都没有获取到属性值,那么属性值将被设置为一个空字符串:''。

属性值获取到了之后,就可以拼装最终的 attrs 数组。

attrs 数组的每个元素对象只包含两个元素,即属性名 name 和属性值 value ,对于属性名直接从 args[1] 中即可获取,但我们发现属性值却没有直接使用前面获取到的 value ,而是将传value 递给了decodeAttr 函数,并使用该函数的返回值作为最终的属性值。

decodeAttr 函数的作用是对属性值中所包含的 html 实体进行解码,将其转换为实体对应的字符。关于 shouldDecodeNewlinesForHref 与 shouldDecodeNewlines 可回顾章节

Vue编译器源码分析compileToFunctions作用

接下来是:

if (!unary) {
	stack.push({
		tag: tagName,
		lowerCasedTag: tagName.toLowerCase(),
		attrs: attrs
	});
	lastTag = tagName;
}

这个if条件是当开始标签是非一元标签时才会执行,其目的是: 如果开始标签是非一元标签,则将该开始标签的信息入栈,即push到stack数组中,并将lastTag的值设置为该标签名。

在讲解 parseHTML 函数开头定义的变量和常量的过程中,我们讲解过 stack 常量以及lastTage 变量,其目的是将来判断是否缺少闭合标签,并且现在大家应该知道为什么 lastTag 所存储的标签名字始终保存着 stack 栈顶的元素了。

调用parser钩子函数

最后一段代码调用parser钩子函数的:

if (options.start) {
	options.start(tagName, attrs, unary, match.start, match.end);
}

如果 parser 选项中包含 options.start 函数,则调用之,并将开始标签的名字 tagName ,格式化后的属性数组 attrs ,是否为一元标签 unary ,以及开始标签在原 html 中的开始和结束位置match.start 和 match.end 作为参数传递。

接下来我们分析 parse 到结束标签之后会怎么做。

parseHTML 函数源码解析之解析器遇到结束标签

以上就是vue parseHTML 函数源码解析的详细内容,更多关于vue parseHTML 函数的资料请关注编程网其它相关文章!

阅读原文内容投诉

免责声明:

① 本站未注明“稿件来源”的信息均来自网络整理。其文字、图片和音视频稿件的所属权归原作者所有。本站收集整理出于非商业性的教育和科研之目的,并不意味着本站赞同其观点或证实其内容的真实性。仅作为临时的测试数据,供内部测试之用。本站并未授权任何人以任何方式主动获取本站任何信息。

② 本站未注明“稿件来源”的临时测试数据将在测试完成后最终做删除处理。有问题或投稿请发送至: 邮箱/279061341@qq.com QQ/279061341

软考中级精品资料免费领

  • 历年真题答案解析
  • 备考技巧名师总结
  • 高频考点精准押题
  • 2024年上半年信息系统项目管理师第二批次真题及答案解析(完整版)

    难度     813人已做
    查看
  • 【考后总结】2024年5月26日信息系统项目管理师第2批次考情分析

    难度     354人已做
    查看
  • 【考后总结】2024年5月25日信息系统项目管理师第1批次考情分析

    难度     318人已做
    查看
  • 2024年上半年软考高项第一、二批次真题考点汇总(完整版)

    难度     435人已做
    查看
  • 2024年上半年系统架构设计师考试综合知识真题

    难度     224人已做
    查看

相关文章

发现更多好内容

猜你喜欢

AI推送时光机
位置:首页-资讯-前端开发
咦!没有更多了?去看看其它编程学习网 内容吧
首页课程
资料下载
问答资讯