首页 » 前端 » 正文

JavaScript模板引擎Nunjucks

接触低代码后才认识了这个家伙:

  • 提供丰富的语言特性和块继承、自动转移、宏和异步控制等等。
  • 模板引擎就是基于模板配合数据构造出链输出的一个组件。
  • 尽可能情况下,我们都需要读取数据后渲染模板,然后呈现给用户。故我们需要约会对应的模板引擎。
  • 简单来说,Nunjucks就实现了在后台服务器显示内容的模板。

下面来看看一些使用方法

一、node上的基本使用

nunjucks.render(name, [context], [callback])

// 引用
import nunjucks from 'nunjucks';
// 渲染模板
var res = nunjucks.render('foo.html', { username: 'James' });

然后在模板foo.html中就可以使用username字段了

<body>
{{username}}
</body>

二、多模板管理

在 node 端使用 FileSystemLoader 加载模板,浏览器端则使用 WebLoader 通过 http 加载(或使用编译后的模板)。

很显然,上面单独一个模板应用并不能满足日常需求,而对于低代码平台来说,模板的作用在于通过node生成对应的js文件,比如,我们要通过一个json来生成目标文件中的js方法等。

// 1、这句可以理解为模板引擎所识别的模板文件目录
const file_loader = new nunjucks.FileSystemLoader(moduleType, {})
// 2、模板引用实例化,这时候才算是引入路径
const env = new nunjucks.Environment(file_loader)
// 3、渲染模板,获取渲染结果
let context = env.render('模板.js', {key: value})
// 4、生成新文件
creatFile(path, '目标文件.js', context)

1、有几点需要注意的是,FileSystemLoader里的第二个参数可以为空,一般不常用,不过可以添加autoescape: true,nunjuck 会转义所有的输出,为了安全建议一直开启。

2、我们前面说了这是node生成代码,所以第3步中获取数据流context,在第4步中写入,path是目标文件路径。 3、在第2步后面,还可以添加一个addFilter,可以理解你给模板引擎定义了一个内置方法,在模板中使用数据变量的时候可以调用{{shorten|shorten}}

env.addFilter('shorten', function(str, count) {  
    return str.slice(0, count || 5);  
});

还有更多定义和参数方法,这里不再一一赘述,可以看官网,就目前这些方法应该可以满足一个复杂应用的使用。

三、模板使用

前面说了很多关于引用库文件的方法,下面就是重头戏了,也是大家最关心的模板问题,毕竟要通过模板生产目标文件的。

1、基本变量使用,前面我们是这么执行的env.render('模板.js', {key: value}),那么js里就可以直接使用

// 普通的js文件(当作模板)
{{key}}
// 如果key是一个对象,开发过程中还可以通过过滤实现完全输出
{{key|dump}}
// 还记得前面我们通过addFilter定义了一个过滤器shorten,只不过dump是库给定义的,shorten是我们自定义的
{{key|shorten}}

2、除了基本数据类型就是array、object了

// 这是一个html的引用
{% for item in usersArr%}
    <li>
        姓名是: {{item.name}}
        年龄是: {{item.age}}
    </li>
{% endfor %} 
<!-- 注意在循环结束时,给一个结束的标志--> 

// 如果是js模板也一样,这里是循环eventDefinition,生成方法定义的过程
{% for key, value in eventDefinition %}
{{ key }}={(e) => {
  (Events.{{ item.name }} && typeof {{ item.name }}_{{key}}_execute==='function') ? {{ item.name }}_{{key}}_方法名(e) : ''
}}
{% endfor %} 

3、条件判断,就像写js一样,有着各种语法

{% if arr.length===0 %}
    {{ "直接输出:没数据" }}
{% else %}
    {{"这是第一个结果:"+arr[0]}}
{% endif %}

4、再看一个复杂一点的。这里通过macro定义了一个方法traverseArry,这样你在模板中就可以使用这个方法了。

{% macro traverseArry(array) %}
    {% for item in array %}
        {% if item is object%}
            { {% for k , v in item %} 
                {{k}} : {{v|safe}}, 
            {% endfor %} },
        {% else %}
            {{ item|safe}}
        {% endif %}
   {% endfor %}
{% endmacro %}

综上来看,Nunjucks在逻辑上跟我们常见的js没有太大区别,主要的还是语法问题,是不是挺简单的。

四、注意事项

1、模块加载

我们在模板中可以加载另一个模板js,这样才有了上面macro定义方法达到共用的目的,除了这种定向的,我们在实际应用中也会遇到动态加载的问题,你可能想到用条件判断进行import,比如:

{% if usePubTemp %}
    {% import "../模板1.js" as Common %}
{% else %}
    {% import "新路径/模板2.js" as Common %}
{% endif %}

但是你这样会发现,它加载失败了,因为import外不可条件判断,正确的做法是定义一个路径变量

{% if usePubTemp %}
    {% set templatePath = "../模板1.js" %}
{% else %}
    {% set templatePath = "新路径/模板2.js" %}
{% endif %}

{% import templatePath as Common %}

2、多模板载入

上面我们进行了路径条件判断实现不同模板加载的方式,但是有个容易忽略的问题,就是新路径新路径/模板2.js也要在node中添加到,否则识别不到。前面我们说Environment来实例化模板路径,它第一个参数可以传一个路径,也可以是路径数组,可以支持多个路径的情况。

3、js语法和模板语法混用

很明显两者语法思路一样,写法不同,在写js模板的时候要特别注意,到底是要做逻辑还是要输出,否则很容易出现错误的结果。

// 比如模块加载,你体会一下会变成什么
{% if usePubTemp %}
    {{ import "../模板1.js" as Common }}
{% else %}
    {{ import "新路径/模板2.js" as Common }}
{% endif %}

好了,以上就是js模板引擎Nunjucks的一些常见使用方法了,有兴趣的同学可以试试。