Vue源码之mustache模板引擎

260 阅读4分钟

1.何为模板引擎?

即将数据要变为视图的最优雅的解决方案。

如Vue的解决方法:

 <li v-for="item in arr"></li>  

这种实际上就是一种模板引擎。

2.历史上曾出现的数据变为视图的方法:

l  纯DOM法

l  数组join法:本质就是字符串的方法

l  ES6的反引号法:ES6中新增了${}语法,可以非常快地把变量拼到字符串里而不用像字符串那样要斩断连接

l  模板引擎:解决数据变为视图的最优雅的方法

3. mustache

mustache用{{ }}作为嵌入标记。是最早的模板引擎库,它的底层实现机理为后续模板引擎的发展提供了崭新的思路

{{ }}的语法也被Vue沿用。

4.mustache库的基本使用:

1. 必须引入mustache库,可以在bootcdn.cn上找到它

注:最新版的mustache库浏览器不支持模块导入,4.0.1版本的可以

2. mustache模板语法如下:

#arr表示开始循环arr数组,/arr表示arr数组循环结束

Snipaste_2022-10-15_00-00-56.jpg

3. 注入数据的方法:Mustache.render(templateStr,data);

第一个参数是模板字符串,第二个参数是数组中的数据

如:

①  不循环数组: Snipaste_2022-10-15_00-16-16.jpg

②  循环简单数组:使用.标识每一项数据 Snipaste_2022-10-15_00-13-09.jpg

③  数组的嵌套

Snipaste_2022-10-15_00-19-11.jpg

4. mustache库的机理

Snipaste_2022-10-15_00-29-25.jpg mustache库底层重点要做:

①  将模板字符串编译为tokens形式

② 将tokens结合数据解析为dom字符串

5.tokens

tokens就是模板字符串的JS表示。

Snipaste_2022-10-15_00-40-45.jpg

6.手写实现mustache关键源码

1.

首先创建一个新文件夹然后命令行输入npm init初始化项目,然后用webpack进行模块打包。(官方库用的是rollup,但webpack可以让我们更方便地在浏览器中实时调试程序)

2. 手写实现mustache环境配置:

其实webpack.config.js文件起到的作用就是在8080提供一个静态服务能把www文件夹的东西静态地显示出来,能把src里的js文件虚拟打包到虚拟路径中

Snipaste_2022-10-15_00-46-44.jpg

3. 将package.json中的script属性改为

"scripts": { "dev": "webpack-dev-server" },使之可以通过npm run dev执行

4. Scanner类:扫描器类

scan和scanUtil两个方法的目的:

Snipaste_2022-10-15_01-01-17.jpg

scan方法:功能弱,只是走过指定内容,无返回值

scanUtil方法:让指针进行扫描,直到遇见指定内容结束,且能返回结束之前路过的文字

5. 将模板字符串变为tokens数组:

新建一个parseTemplateToTokens.js文件让扫描器工作,通过if……else if……else语句收集开始标记出现之前的文字

Snipaste_2022-10-15_01-11-16.jpg

6. 将零散的tokens嵌套起来:

利用栈的先进后出的特点,遍历所有的tokens。

新建一个nextTokens.js文件将

首先准备一个结果数组、一个栈结构存放当前操作的tokens小数组和一个收集器。

var nestedTokens = []; var sections = []; var collector = nestedTokens;

收集器充分利用了js的引用类型值的特性,它会把#/之间的token整合起来放进这个收集器中,然后把这个收集器放入当前token中作为它的下标为3的项。

即相当于每进一层就创建一个新的容器来存这一层的数据。且引用类型只是改变地址,并不会影响原对象。

Snipaste_2022-10-15_01-41-09.jpg

7. 将tokens数组结合数据解析为dom字符串

新建一个renderTemplate.js文件和parseArray文件

renderTemplate.js文件通过遍历tokens数组将它们拼到定义的结果字符串中。

Snipaste_2022-10-15_01-52-13.jpg

由于数据中可能会有多层对象嵌套的形式,且js不认识点符号,所以需要另外新建一个lookup.js函数使之可在多层对象中深入取得数据

Snipaste_2022-10-15_01-53-59.jpg

如果没有点符号就可以直接返回了

而#标记的tokens需要递归处理它下标为2的小数组,所以parseArray文件用于处理数组,结合renderTemplate实现递归。这个函数递归调用的次数由data决定。

将整体数据data中这个数组要使用的部分定义为v,然后遍历v数组,如果数组长度小于0则直接返回结果字符串

Snipaste_2022-10-15_01-56-00.jpg