自己实现一个 Mustache 模板引擎 2 : Mustache 模板引擎 的原理剖析

这是我参与更文挑战的第 2 天,活动详情查看: 更文挑战

前言:

作为一名前端人,对于 ECMAScript( JavaScript) 这门语言是否有深入的了解,决定我们能走得多远,尤其再今天,只是我们经常使用 Vue、React 等框架进行视图渲染,框架封装了太多底层,是时候研究一下底层源码,看看这些框架是如何将一个个数据渲染成为视图的,接下来我们就从零开始自己实现一个 Mustache 模板引擎的第二天正式,为了不水文,我决定今天直入正题 剖析 Mustache 模板引擎 的原理。

首先对于造轮子而言,我们一定要明确自己的目的:

  1. 学会使用轮子;
  2. 了解轮子的原理;
  3. 自己造一个轮子

这样来一步一步提升自己

官方安装的安装等教程在这里就不太多介绍了,也建议大家有能力的多看看官方文档。

0. Mustache 模板引擎 的简介

image.png

  • 模板引擎是将数据要变为视图最优雅的解决方案

  • Mustache官方git: github.com/janl/mustac…

  • Mustache是“胡子”的意思,因为它的嵌入标记{{ }}非常像胡子 • 没错,{{ }}的语法也被Vue沿用,这就是我们学习mustache的原因

  • Mustache是最早的模板引擎库,比Vue诞生的早多了,它的底层实现机理在当 时是非常有创造性的、轰动性的,为后续模板引擎的发展提供了崭新的思路

1. Mustache 模板引擎 的基本使用

  • 变量渲染

    {{ name }}

    变量写在{{ }} 内 ,这和 Vue 模版是不是一摸一样?没错,就是因为 Vue 模版引擎也借鉴了 Mustache 的思想。

    <body>
        <div id="container"></div>
    
        <script src="jslib/mustache.js"></script>
        <script>
            var templateStr = `
                <h1>我买了一个{{thing}},好{{mood}}啊</h1>
            `;
    
            var data = {
                thing: '华为手机',
                mood: '开心'
            };
    
            var domStr = Mustache.render(templateStr, data);
            
            var container = document.getElementById('container');
            container.innerHTML = domStr;
        </script>
    </body>
    复制代码

    视图渲染如下

    ![image-20210602225031019](/Users/chenuvi/Library/Application Support/typora-user-images/image-20210602225031019.png)

  • 循环对象数组

    <body>
        <div id="container"></div>
    
        <!-- 模板 -->
        <script type="text/template" id="mytemplate">
            <ul>
                {{#arr}}
                    <li>
                        <div class="hd">{{name}}的基本信息</div>    
                        <div class="bd">
                            <p>姓名:{{name}}</p>    
                            <p>性别:{{sex}}</p>    
                            <p>年龄:{{age}}</p>    
                        </div>
                    </li>
                {{/arr}}
            </ul>
        </script>
    
        <script src="jslib/mustache.js"></script>
        <script>
            var templateStr = document.getElementById('mytemplate').innerHTML;
    
            var data = {
                arr: [
                    { "name": "小明", "age": 12, "sex": "男" },
                    { "name": "小红", "age": 11, "sex": "女" },
                    { "name": "小强", "age": 13, "sex": "男" }
                ]
            };
                  
                  
    				// 将视图字符串
            var domStr = Mustache.render(templateStr, data);
            var container = document.getElementById('container');
            container.innerHTML = domStr;
        </script>
    </body>
    
    复制代码

    ![image-20210602225127790](/Users/chenuvi/Library/Application Support/typora-user-images/image-20210602225127790.png)

  • 数组的嵌套

    <body>
        <div id="container"></div>
    
        <script src="jslib/mustache.js"></script>
        <script>
            var templateStr = `
                <ul>
                    {{#arr}}
                        <li>
                            {{name}}的爱好是:
                            <ol>
                                {{#hobbies}} 
                                    <li>{{.}}</li>
                                {{/hobbies}} 
                            </ol>
                        </li>    
                    {{/arr}}
                </ul>
            `;
    
            var data = {
                arr: [
                    {'name': '小明', 'age': 12, 'hobbies': ['游泳', '羽毛球']},
                    {'name': '小红', 'age': 11, 'hobbies': ['编程', '写作文', '看报纸']},
                    {'name': '小强', 'age': 13, 'hobbies': ['打台球']},
                ]
            };
    
            var domStr = Mustache.render(templateStr, data);
            
            var container = document.getElementById('container');
            container.innerHTML = domStr;
        </script>
    </body>
    复制代码

    ![image-20210602225215957](/Users/chenuvi/Library/Application Support/typora-user-images/image-20210602225215957.png)

在这里我们可以看到, Mustache 模版引擎还是比较强大的,可以对变量,数组以及嵌套数组灵活的渲染,那么他是如何做到的呢 ?

2. 初窥Mustache 模版引擎的原理

我们将 Mustache 下载到本地, 修改一下 ,再 这里 log 一下:

image-20210602231346740.png

先不管这个 tokens 到底是什么,在控制台看看 渲染循环对象数组 的时候到底输出了什么

image-20210602230450230.png

可以看到,tokens 在这里成了一个数组,并对我们要渲染的变量做了一些标记,每个数字第 0 项 有"text" "#" "name" 标记 ,这些分别就代表了变量的类型, "text" 表示文本,"#" 表示数组 , "name" 则表示普通变量。

3. Mustache 模版引擎的原理

什么是 tokens

  • tokens是一个JS的嵌套数组,说白了,就是模板字符串的JS表示

  • 它是“抽象语法树”、“虚拟节点”等等的开山鼻祖

模板字符串: <h1>我买了一个{{thing}},好{{mood}}啊</h1>

tokens : 这里数组的每一项都是一个 token,共同组成了 tokens

image-20210602231346740.png

Mustache库的机理

mustache库底层重点要做两个事情:

  1. 将模板字符串编译为tokens形式
  2. 将tokens结合数据,解析为dom字符串

image-20210602231659525.png

最后 会将 dom字符串插入到相应的视图容器内渲染。

结语

好了,今天的内容就到这里啦,谢谢 ? 大家的观看,如果喜欢的话,请为我点个赞吧!

作者:chenuvi

邮箱: chenui@outlook.com

© 版权声明
THE END
喜欢就支持一下吧
点赞0 分享