vue.js

关注公众号 jb51net

关闭
首页 > 网络编程 > JavaScript > javascript类库 > vue.js > vue parseHTML函数AST预备

vue parseHTML函数源码解析 AST预备知识

作者:李李

这篇文章主要为大家介绍了vue parseHTML函数源码解析 AST预备知识示例详解,有需要的朋友可以借鉴参考下,希望能够有所帮助,祝大家多多进步,早日升职加薪

正文

接上章节:parseHTML 函数源码解析AST 基本形成

在正式扎进Vue parse源码之前,我们先了解下他周边的工具函数, 这能帮我们快速的去理解阅读。

还记得我们在上章节讲的element元素节点的描述对象吗?

var element = {
	type: 1,
	tag: tag,
	parent: null,
	attrsList: attrs,
	children: []
}

在源码中定义了一个createASTElement函数,用来创建一个元素的描述对象。

createASTElement函数

function createASTElement(tag, attrs, parent) {
		return {
			type: 1,
			tag: tag,
			attrsList: attrs,
			attrsMap: makeAttrsMap(attrs),
			parent: parent,
			children: []
		}
	}

解析指令所用正则

var onRE = /^@|^v-on:/;
var dirRE = /^v-|^@|^:/;
var forAliasRE = /([\s\S]*?)\s+(?:in|of)\s+([\s\S]*)/;
var forIteratorRE = /,([^,\}\]]*)(?:,([^,\}\]]*))?$/;
var stripParensRE = /^\(|\)$/g;
var argRE = /:(.*)$/;
var bindRE = /^:|^v-bind:/;
var modifierRE = /\.[^.]+/g;

在解析开始标签的时候你遇到的不仅有属性,还有一些Vue 自定义的指令。下面一起来分析下解析指令会有用哪些正则。

onRE

var onRE = /^@|^v-on:/;

匹配以字符 @ 或 v-on: 开头的字符串,主要作用是检测标签属性名是否是监听事件的指令。

dirRE

var const dirRE = /^v-|^@|^:/

匹配以字符 v- 或 @ 或 : 开头的字符串,主要作用是检测标签属性名是否是指令。在Vue中所有以 v- 开头的属性都被认为是指令,另外@字符是 v-on 的缩写,: 字符是 v-bind 的缩写。

forAliasRE

var forAliasRE = /([\s\S]*?)\s+(?:in|of)\s+([\s\S]*)/;

匹配 v-for 属性的值,并捕获 in 或 of 前后的字符串。都是正则大神就不解释怎么捕获的了。

forIteratorRE

var forIteratorRE = /,([^,\}\]]*)(?:,([^,\}\]]*))?$/;

这个也是匹配v-for的属性值,不过比之前要稍微复杂点:列表渲染 v-for(https://cn.vuejs.org/v2/guide/list.html)需要先了解下这个。

//示例:1
<div v-for="(value, name) in object">
  {{ name }}: {{ value }}
</div>
//示例:2 
<div v-for="(value, name, index) in object">
  {{ index }}. {{ name }}: {{ value }}
</div>

没错就是用来捕获,示例1中的:'obj , index' 示例2中的:'value, key, index' 。

stripParensRE

var stripParensRE = /^\(|\)$/g;

这个捕获组用来捕获要么以字符 ( 开头,要么以字符 ) 结尾的字符串,或者两者都满足。那么这个正则的作用是什么呢?我们在讲解正则 forIteratorRE 时有个细节不知道大家注意到了没有,就是 forIteratorRE 正则所匹配的字符串是 'obj, index' ,而不是 '(obj, index)' ,这两个字符串的区别就在于第二个字符串拥有左右括号,所以在使用 forIteratorRE 正则之前,需要使用 stripParensRE 正则去掉字符串 '(obj, index)' 中的左右括号,实现方式很简单:

"(obj, index)".replace(stripParensRE, "")

argRE

var argRE = /:(.*)$/;

argRE正则用来匹配指令编写中的参数,并且拥有一个捕获组,用来捕获参数的名字。

示例:

<div v-on:click.item="handle"></div>

其中 v-on 为指令,click为传递给 v-on 指令的参数,stop 为修饰符。

bindRE

var bindRE = /^:|^v-bind:/;

该正则用来匹配以字符:或字符串 v-bind: 开头的字符串,主要用来检测一个标签的属性是否是绑定(v-bind)。

modifierRE

var modifierRE = /\.[^.]+/g;

该正则用来匹配修饰符的,但是并没有捕获任何东西,但你可以用match、exec等方法获取与当前正则匹配成功的信息。

parse 函数中的变量

在讲解 parse 函数直接我们还需要先了解下它内部所定义的一些变量以及用途。

function parse(template, options) {
	warn$2 = options.warn || baseWarn;
	platformIsPreTag = options.isPreTag || no;
	platformMustUseProp = options.mustUseProp || no;
	platformGetTagNamespace = options.getTagNamespace || no;
	transforms = pluckModuleFunction(options.modules, 'transformNode');
	preTransforms = pluckModuleFunction(options.modules, 'preTransformNode');
	postTransforms = pluckModuleFunction(options.modules, 'postTransformNode');
	delimiters = options.delimiters;
	var stack = [];
	var preserveWhitespace = options.preserveWhitespace !== false;
	var root;
	var currentParent;
	var inVPre = false;
	var inPre = false;
	var warned = false;
	function warnOnce(msg) {
        //...
	}
	function closeElement(element) {
       //...
	}
	parseHTML(template, {
		warn: warn$2,
		expectHTML: options.expectHTML,
		isUnaryTag: options.isUnaryTag,
		canBeLeftOpenTag: options.canBeLeftOpenTag,
		shouldDecodeNewlines: options.shouldDecodeNewlines,
		shouldDecodeNewlinesForHref: options.shouldDecodeNewlinesForHref,
		shouldKeepComment: options.comments,
		start: function start(tag, attrs, unary) {},
		end: function end() {},
		chars: function chars(text) {},
		comment: function comment(text) {},
	});
	return root
}

我们先来看下针对web平台初始化的一些变量。

warn$2 = options.warn || baseWarn;
platformIsPreTag = options.isPreTag || no;
platformMustUseProp = options.mustUseProp || no;
platformGetTagNamespace = options.getTagNamespace || no;
transforms = pluckModuleFunction(options.modules, 'transformNode');
preTransforms = pluckModuleFunction(options.modules, 'preTransformNode');
postTransforms = pluckModuleFunction(options.modules, 'postTransformNode');
delimiters = options.delimiters;

继续往下看:

var stack = [];
var preserveWhitespace = options.preserveWhitespace !== false;
var root;
var currentParent;
var inVPre = false;
var inPre = false;
var warned = false;

好了一些边边角角的东西就先讲到这,接下来我们一起来分析Vue parse源码看看一颗完整的AST树是如何构建出来的。更多关于vue parseHTML函数AST预备的资料请关注脚本之家其它相关文章!

您可能感兴趣的文章:
阅读全文