引言

在上篇文章 Vue编译器源码分析compileToFunctions作用中我们介绍到了,在 compileToFunctions 方法中:

// compile
var compiled = compile(template, options);

而真正的编译工作是依托于 compile 函数,接下来我们详细解析 compile 。

解析 compile

上述代码在调用 compile ,其中模板字符串 template ,选项参数 options 第二个参数传递给 compile 函数,在章节三种我们知道,这里传递过去的options如下:

{
	shouldDecodeNewlines,
	shouldDecodeNewlinesForHref,
	delimiters,
	comments,
	warn 
}

compile 源码

接下来我们看下 compile 的源码。

function createCompilerCreator(baseCompile) {
	return function createCompiler(baseOptions) {
		function compile(
			template,
			options
		) {
			var finalOptions = Object.create(baseOptions);
			var errors = [];
			var tips = [];
			finalOptions.warn = function(msg, tip) {
				(tip ? tips : errors).push(msg);
			};
			if (options) {
				// merge custom modules
				if (options.modules) {
					finalOptions.modules =
						(baseOptions.modules || []).concat(options.modules);
				}
				// merge custom directives
				if (options.directives) {
					finalOptions.directives = extend(
						Object.create(baseOptions.directives || null),
						options.directives
					);
				}
				// copy other options
				for (var key in options) {
					if (key !== 'modules' && key !== 'directives') {
						finalOptions[key] = options[key];
					}
				}
			}
			var compiled = baseCompile(template, finalOptions); {
				errors.push.apply(errors, detectErrors(compiled.ast));
			}
			compiled.errors = errors;
			compiled.tips = tips;
			return compiled
		}
		return {
			compile: compile,
			compileToFunctions: createCompileToFunctionFn(compile)
		}
	}
}

·首先可以看到:

var finalOptions = Object.create(baseOptions);

配置选项

finalOptions 所有的配置选项最终都会挂载在这个对象上,baseOptions包含编译器在运作的时候所需的配置选项。

var baseOptions = {
	expectHTML: true,
	modules: modules$1,
	directives: directives$1,
	isPreTag: isPreTag,
	isUnaryTag: isUnaryTag,
	mustUseProp: mustUseProp,
	canBeLeftOpenTag: canBeLeftOpenTag,
	isReservedTag: isReservedTag,
	getTagNamespace: getTagNamespace,
	staticKeys: genStaticKeys(modules$1)
};

属性分别解析

  • 第一个属性: expectHTML 被设置为 true 。
  • 第二个属性:modules
var modules$1 = [
	klass$1,
	style$1,
	model$1
];
var klass$1 = {
	staticKeys: ['staticClass'],
	transformNode: transformNode,
	genData: genData
};
var style$1 = {
	staticKeys: ['staticStyle'],
	transformNode: transformNode$1,
	genData: genData$1
};
var model$1 = {
	preTransformNode: preTransformNode
};

我们用到了在细讲。

  • 第三个属性:directives 值是三个属性 (model、text、html) 的对象,且属性的值都是函数。
  • 第四个属性:isPreTag 它是一个函数,其作用是通过给定的标签名字检查标签是否是 'pre' 标签。
  • 第五个属性:isUnaryTag 是一个通过makeMap生成的函数,该函数的作用是检测给定的标签是否是一元标签。
  • 第六个属性:mustUseProp 它是一个函数,其作用是用来检测一个属性在标签中是否要使用props进行绑定。
  • 第七个属性:canBeLeftOpenTag 一个使用makeMap生成的函数,它的作用是检测非一元标签,但却可以自己补全并闭合的标签。比如 div 标签是一个双标签,你需要这样使用<div> text </div>,但是你依然可以省略闭合标签,直接这样写:<div> text ,且浏览器会自动补全。但是有些标签你不可以这样用,它们是严格的双标签。
  • 第八个属性:isReservedTag 它是一个函数,其作用是检查给定的标签是否是保留的标签。
  • 第九个属性:getTagNamespace 它也是一个函数,其作用是获取元素(标签)的命名空间。
  • 第十个属性:staticKeys 它的值是通过以 modules 为参数调用 genStaticKeys 函数的返回值得到的。 其作用是根据编译器选项的 modules 选项生成一个静态键字符串。

现在我们粗略的介绍了下baseOptions 中各个属性的作用,当我们用到时候再来详细讲解他们的源码。

继续往下看:

var errors = [];
var tips = [];
finalOptions.warn = function(msg, tip) {
	(tip ? tips : errors).push(msg);
};

很简单

finalOptions添加warn 方法

在 finalOptions上添加了 warn 方法,该方法接收两个参数:

  • msg 错误或提示的信息
  • tip 用来标示 msg 是错误还是提示。

warn选项主要用在编译过程中的错误和提示收集,如果收集的信息是错误信息就将错误信息添加到前面定义的errors数组里,如果是提示信息就将其添加到 tips 数组里。

继续:

if (options) {
	// merge custom modules
	if (options.modules) {
		finalOptions.modules =
			(baseOptions.modules || []).concat(options.modules);
	}
	// merge custom directives
	if (options.directives) {
		finalOptions.directives = extend(
			Object.create(baseOptions.directives || null),
			options.directives
		);
	}
	// copy other options
	for (var key in options) {
		if (key !== 'modules' && key !== 'directives') {
			finalOptions[key] = options[key];
		}
	}
}

这段代码检查 options 是否存在,这里的 options 就是使用编译器编译模板时传递的选项参数,或者可以简单理解为调用 compileToFunctions 函数时传递的选项参数。

而baseOptions理解为编译器的默认选项或者基本选项,options 是用来提供定制能力的扩展选项。而上面这段代码的作用,就是将 options 对象混合到 finalOptions 中。

两个特殊的属性处理

  • modules: 如果 options.modules 存在,就在 finalOptions 对象上添加 modules 属性,其值为 baseOptions.modules 和 options.modules 这两个数组合并后的新数组。
  • directives: 对于directives 采用原型链的原理实现扩展属性对基本属性的覆盖。

继续:

var compiled = baseCompile(template, finalOptions); {
	errors.push.apply(errors, detectErrors(compiled.ast));
}
compiled.errors = errors;
compiled.tips = tips;

上面的代码调用了 baseCompile 函数,并分别将字符串模板(template),以及最终的编译器选项(finalOptions)传递了过去。

compiled 是 baseCompile 对模板的编译结果所以上面这段代码的作用是用来通过抽象语法树来检查模板中是否存在错误表达式的,通过 detectErrors 函数实现,将compiled.ast 作为参数传递给 detectErrors 函数,该函数最终返回一个数组,该数组中包含了所有错误的收集,最终通过这句代码将错误添加到errors。

将收集到的错误(errors)和提示(tips)添加到compiled上并返回。

baseCompile 函数是在 createCompilerCreator 函数调用时传递的实参。

// `createCompilerCreator` allows creating compilers that use alternative
// parser/optimizer/codegen, e.g the SSR optimizing compiler.
// Here we just export a default compiler using the default parts.
var createCompiler = createCompilerCreator(function baseCompile(
	template,
	options
) {
	var ast = parse(template.trim(), options);
	if (options.optimize !== false) {
		optimize(ast, options);
	}
	var code = generate(ast, options);
	return {
		ast: ast,
		render: code.render,
		staticRenderFns: code.staticRenderFns
	}
});

从Vue编译器源码分析(一) 到 Vue编译器源码分析(四) 我们已经把编译器整体代码组织的结构讲分析了。

从下章节开始,就正式的进入到Vue编译器词法分析阶段,去看下模板对应的AST(抽象语法树)是怎么形成的。

Vue编译器源码AST 抽象语法树

以上就是Vue编译器解析compile源码解析的详细内容,更多关于Vue编译器compile解析的资料请关注Devmax其它相关文章!

Vue编译器解析compile源码解析的更多相关文章

  1. Vue如何指定不编译的文件夹和favicon.ico

    这篇文章主要介绍了Vue如何指定不编译的文件夹和favicon.ico,具有很好的参考价值,希望对大家有所帮助。如有错误或未考虑完全的地方,望不吝赐教

  2. vue自定义加载指令v-loading占位图指令v-showimg

    这篇文章主要为大家介绍了vue自定义加载指令和v-loading占位图指令v-showimg的示例详解,有需要的朋友可以借鉴参考下,希望能够有所帮助,祝大家多多进步,早日升职加薪

  3. vue使用动画实现滚动表格效果

    这篇文章主要为大家详细介绍了vue使用动画实现滚动表格效果,文中示例代码介绍的非常详细,具有一定的参考价值,感兴趣的小伙伴们可以参考一下

  4. 关于Vue 监控数组的问题

    这篇文章主要介绍了Vue 监控数组的示例,主要包括Vue 是如何追踪数据发生变化,Vue 如何更新数组以及为什么有些数组的数据变更不能被 Vue 监测到,对vue监控数组知识是面试比较常见的问题,感兴趣的朋友一起看看吧

  5. Vue子组件props从父组件接收数据并存入data

    这篇文章主要介绍了Vue子组件props从父组件接收数据并存入data的方法,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习学习吧

  6. Vue h函数的使用详解

    本文主要介绍了Vue h函数的使用详解,文中通过示例代码介绍的非常详细,具有一定的参考价值,感兴趣的小伙伴们可以参考一下

  7. VUE响应式原理的实现详解

    这篇文章主要为大家详细介绍了VUE响应式原理的实现,文中示例代码介绍的非常详细,具有一定的参考价值,感兴趣的小伙伴们可以参考一下,希望能够给你带来帮助

  8. vue+Element ui实现照片墙效果

    这篇文章主要为大家详细介绍了vue+Element ui实现照片墙效果,文中示例代码介绍的非常详细,具有一定的参考价值,感兴趣的小伙伴们可以参考一下

  9. vue+elemet实现表格手动合并行列

    这篇文章主要为大家详细介绍了vue+elemet实现表格手动合并行列,文中示例代码介绍的非常详细,具有一定的参考价值,感兴趣的小伙伴们可以参考一下

  10. iview+vue实现导入EXCEL预览功能

    这篇文章主要为大家详细介绍了iview+vue实现导入EXCEL预览功能,文中示例代码介绍的非常详细,具有一定的参考价值,感兴趣的小伙伴们可以参考一下

随机推荐

  1. js中‘!.’是什么意思

  2. Vue如何指定不编译的文件夹和favicon.ico

    这篇文章主要介绍了Vue如何指定不编译的文件夹和favicon.ico,具有很好的参考价值,希望对大家有所帮助。如有错误或未考虑完全的地方,望不吝赐教

  3. 基于JavaScript编写一个图片转PDF转换器

    本文为大家介绍了一个简单的 JavaScript 项目,可以将图片转换为 PDF 文件。你可以从本地选择任何一张图片,只需点击一下即可将其转换为 PDF 文件,感兴趣的可以动手尝试一下

  4. jquery点赞功能实现代码 点个赞吧!

    点赞功能很多地方都会出现,如何实现爱心点赞功能,这篇文章主要为大家详细介绍了jquery点赞功能实现代码,具有一定的参考价值,感兴趣的小伙伴们可以参考一下

  5. AngularJs上传前预览图片的实例代码

    使用AngularJs进行开发,在项目中,经常会遇到上传图片后,需在一旁预览图片内容,怎么实现这样的功能呢?今天小编给大家分享AugularJs上传前预览图片的实现代码,需要的朋友参考下吧

  6. JavaScript面向对象编程入门教程

    这篇文章主要介绍了JavaScript面向对象编程的相关概念,例如类、对象、属性、方法等面向对象的术语,并以实例讲解各种术语的使用,非常好的一篇面向对象入门教程,其它语言也可以参考哦

  7. jQuery中的通配符选择器使用总结

    通配符在控制input标签时相当好用,这里简单进行了jQuery中的通配符选择器使用总结,需要的朋友可以参考下

  8. javascript 动态调整图片尺寸实现代码

    在自己的网站上更新文章时一个比较常见的问题是:文章插图太宽,使整个网页都变形了。如果对每个插图都先进行缩放再插入的话,太麻烦了。

  9. jquery ajaxfileupload异步上传插件

    这篇文章主要为大家详细介绍了jquery ajaxfileupload异步上传插件,具有一定的参考价值,感兴趣的小伙伴们可以参考一下

  10. React学习之受控组件与数据共享实例分析

    这篇文章主要介绍了React学习之受控组件与数据共享,结合实例形式分析了React受控组件与组件间数据共享相关原理与使用技巧,需要的朋友可以参考下

返回
顶部