Nunjucks是什么东东?其实它是一个模板引擎

那什么是模板引擎?

模板引擎就是基于模板配合数据构造出字符串输出的一个组件。比如下面的函数就是一个模板引擎:

function examResult (data) {
return `${data.name}同学一年级期末考试语文${data.chinese}分,数学${data.math}分,位于年级第${data.ranking}名。`
}

如果我们输入数据如下:

examResult({
name: '小明',
chinese: 78,
math: 87,
ranking: 999
});

该模板引擎把模板字符串里面对应的变量替换以后,就可以得到以下输出:

小明同学一年级期末考试语文78分,数学87分,位于年级第999名。
function examResult (data) {
return `${data.name}同学一年级期末考试语文${data.chinese}分,数学${data.math}分,位于年级第${data.ranking}名。`
} ret = examResult({
name: '小明',
chinese: 78,
math: 87,
ranking: 999
}); console.log(ret)

模板引擎最常见的输出就是输出网页,也就是HTML文本。当然,也可以输出任意格式的文本,比如Text,XML,Markdown等等。

有同学要问了:既然JavaScript的模板字符串可以实现模板功能,那为什么我们还需要另外的模板引擎?

因为JavaScript的模板字符串必须写在JavaScript代码中,要想写出新浪首页这样复杂的页面,是非常困难的。

输出HTML有几个特别重要的问题需要考虑:

转义

对特殊字符要转义,避免受到XSS攻击。比如,如果变量name的值不是小明,而是小明<script>...</script>,模板引擎输出的HTML到了浏览器,就会自动执行恶意JavaScript代码。

格式化

对不同类型的变量要格式化,比如,货币需要变成12,345.00这样的格式,日期需要变成2016-01-01这样的格式。

简单逻辑

模板还需要能执行一些简单逻辑,比如,要按条件输出内容,需要if实现如下输出:

{{ name }}同学,
{% if score >= 90 %}
成绩优秀,应该奖励
{% elif score >=60 %}
成绩良好,继续努力
{% else %}
不及格,建议回家打屁股
{% endif %}

所以,我们需要一个功能强大的模板引擎,来完成页面输出的功能。

Nunjucks

我们选择Nunjucks作为模板引擎。Nunjucks是Mozilla开发的一个纯JavaScript编写的模板引擎,

既可以用在Node环境下,又可以运行在浏览器端。但是,主要还是运行在Node环境下,因为浏览器端有更好的模板解决方案,例如MVVM框架。

如果你使用过Python的模板引擎jinja2,那么使用Nunjucks就非常简单,两者的语法几乎是一模一样的,因为Nunjucks就是用JavaScript重新实现了jinjia2

从上面的例子我们可以看到,虽然模板引擎内部可能非常复杂,但是使用一个模板引擎是非常简单的,因为本质上我们只需要构造这样一个函数:

function render(view, model) {
// TODO:...
}

其中,view是模板的名称(又称为视图),因为可能存在多个模板,需要选择其中一个。model就是数据,在JavaScript中,它就是一个简单的Object。render函数返回一个字符串,就是模板的输出。

下面我们来使用Nunjucks这个模板引擎来编写几个HTML模板,并且用实际数据来渲染模板并获得最终的HTML输出。

我们创建一个use-nunjucks的VS Code工程结构如下:

use-nunjucks/
|
+- .vscode/
| |
| +- launch.json <-- VSCode 配置文件
|
+- views/
| |
| +- hello.html <-- HTML模板文件
|
+- app.js <-- 入口js
|
+- package.json <-- 项目描述文件
|
+- node_modules/ <-- npm安装的所有依赖包

其中,模板文件存放在views目录中。

我们先在package.json中添加nunjucks的依赖:

"nunjucks": "2.4.2"

注意,模板引擎是可以独立使用的,并不需要依赖koa。用npm install安装所有依赖包。

紧接着,我们要编写使用Nunjucks的函数render。怎么写?方法是查看Nunjucks的官方文档,仔细阅读后,在app.js中编写代码如下:

const nunjucks = require('nunjucks');

function createEnv(path, opts) {

    // 我们用autoescape = opts.autoescape && true这样的代码给每个参数加上默认值

    var
autoescape = opts.autoescape === undefined ? true : opts.autoescape,
noCache = opts.noCache || false,
watch = opts.watch || false,
throwOnUndefined = opts.throwOnUndefined || false,
env = new nunjucks.Environment( // new nunjucks.FileSystemLoader('views')创建一个文件系统加载器 从views目录读取模板。 new nunjucks.FileSystemLoader('views', {
noCache: noCache,
watch: watch,
}), {
autoescape: autoescape,
throwOnUndefined: throwOnUndefined
});
if (opts.filters) {
for (var f in opts.filters) {
env.addFilter(f, opts.filters[f]);
}
}
return env;
} // 变量env就表示Nunjucks模板引擎对象,它有一个render(view, model)方法,正好传入view和model两个参数,并返回字符串。
var env = createEnv('views', {
watch: true,
filters: {
hex: function (n) {
return '0x' + n.toString(16);
}
}
});

变量env就表示Nunjucks模板引擎对象,它有一个render(view, model)方法,正好传入viewmodel两个参数,并返回字符串。

创建env需要的参数可以查看文档获知。我们用autoescape = opts.autoescape && true这样的代码给每个参数加上默认值,最后使用new nunjucks.FileSystemLoader('views')创建一个文件系统加载器,从views目录读取模板。

我们编写一个hello.html模板文件,放到views目录下,内容如下:

<h1>Hello {{ name }}</h1>

然后,我们就可以用下面的代码来渲染这个模板:

var s = env.render('hello.html', { name: '小明' });
console.log(s);

获得输出如下:

<h1>Hello 小明</h1>

咋一看,这和使用JavaScript模板字符串没啥区别嘛。不过,试试:

var s = env.render('hello.html', { name: '<script>alert("小明")</script>' });
console.log(s);

获得输出如下:

<h1>Hello &lt;script&gt;alert("小明")&lt;/script&gt;</h1>

这样就避免了输出恶意脚本。

此外,可以使用Nunjucks提供的功能强大的tag,编写条件判断、循环等功能,例如:

<!-- 循环输出名字 -->
<body>
<h3>Fruits List</h3>
{% for f in fruits %}
<p>{{ f }}</p>
{% endfor %}
</body>

Nunjucks模板引擎最强大的功能在于模板的继承。仔细观察各种网站可以发现,网站的结构实际上是类似的,头部、尾部都是固定格式,只有中间页面部分内容不同。如果每个模板都重复头尾,一旦要修改头部或尾部,那就需要改动所有模板。

更好的方式是使用继承。先定义一个基本的网页框架base.html

<html><body>
{% block header %} <h3>Unnamed</h3> {% endblock %}
{% block body %} <div>No body</div> {% endblock %}
{% block footer %} <div>copyright</div> {% endblock %}
</body>

base.html 定义了三个可编辑的块,分别命名为 headerbody 和 footer 。子模板可以有选择地对块进行重新定义:

{% extends 'base.html' %}

{% block header %}<h1>{{ header }}</h1>{% endblock %}

{% block body %}<p>{{ body }}</p>{% endblock %}

然后,我们对子模板进行渲染:

console.log(env.render('extend.html', {
header: 'Hello',
body: 'bla bla bla...'
}));

输出HTML如下:

<html><body>
<h1>Hello</h1>
<p>bla bla bla...</p>
<div>copyright</div> <-- footer没有重定义,所以仍使用父模板的内容
</body>

Nunjucks的更多相关文章

  1. nunjucks.js模板渲染

    直接用 script 引入文件: <script src="nunjucks.js"></script> 是使用 render 来直接渲染文件,这种方式支持 ...

  2. Koa与Node.js开发实战(3)——Nunjucks模板在Koa中的应用(视频演示)

    技术架构: ​ 在Koa中应用Nunjucks,需要先把Nunjucks集成为符合Koa规格的中间件(Middleware),从本质上来讲,集成后的中间件的作用是给上下文对象绑定一个render(vi ...

  3. Nunjucks:Mozilla 开发的 JavaScript 模板引擎

    Nunjucks 中文网站:https://nunjucks.bootcss.com/

  4. iKcamp|基于Koa2搭建Node.js实战(含视频)☞ 视图Nunjucks

    视频地址:https://www.cctalk.com/v/15114923888328 视图 Nunjucks 彩虹是上帝和人类立的约,上帝不会再用洪水灭人. 客户端和服务端之间相互通信,传递的数据 ...

  5. 前端模板Nunjucks简介

    参考资料: https://mozilla.github.io/nunjucks/ https://mozilla.github.io/nunjucks/templating.html https:/ ...

  6. nunjucks如何使用?

    基本的使用 const nunjucks = require('nunjucks') // nunjucks.configure({ autoescape: true }); // const res ...

  7. nunjucks模板设计一个页面

    使用nunjucks代替原来的ejs,因为这个更强大,是node中主流的模板引擎 nunjucks官网 配置使用 nunjucks 模板引擎 nunjucks 模板引擎没有对模板文件名的后缀名做特定限 ...

  8. 2015年最佳的12个 CSS 开发工具推荐

    CSS所能做的就是改变网页的布局.排版和调整字间距等,但编写 CSS 并不是一项容易的任务,当你接触新的 CSS3 属性及其各自的浏览器前缀的时候,你会发现很伤脑经.值得庆幸的是一些优秀的开发人员提供 ...

  9. 在 2016 年学 JavaScript 是一种什么样的体验?

    转 译者:方应杭 嘿,我最近接到一个 Web 项目,不过老实说,我这两年没怎么接触 Web 编程,听说 Web 技术已经发生了一些变化.听说你是这里对新技术最了解的 Web 开发工程师? 准确地说,我 ...

  10. github上最全的资源教程-前端涉及的所有知识体系

    前面分享了前端入门资源汇总,今天分享下前端所有的知识体系. 个人站长对个人综合素质要求还是比较高的,要想打造多拉斯自媒体网站,不花点心血是很难成功的,学习前端是必不可少的一个环节, 当然你不一定要成为 ...

随机推荐

  1. Wordpress给每一个分类栏目定制不同的广告位

    给分类栏目添加广告位,等同于添加自定义字段. 如果需要依据不同的栏目给广告位添加不同的tag来源,需要在模板页面中获取栏目的分类别名,读取不同的广告. 图1 如图1所示添加新的图片输入框 1. 实现的 ...

  2. leaflet 用自定义pane实现图层顺序调整

    在 Leaflet 中,map panes 隐式地将图层组合在一起,而开发者并不知道这一点.这种分组允许 Web 浏览器以比单独处理图层更有效的方式同时处理多个图层. Map panes 使用 z-i ...

  3. angular路由跳转并传值的多种方式

    Angular的学习使用过程中,路由跳转支撑了项目的全过程,所以路由跳转是一个很常见也是一个很容易忽略的点,,对于页面之间的跳转有着很多的问题,跳转的方式/如何携带参数跳转,下面是自己在学习过程中对a ...

  4. 统计学习:EM算法及其在高斯混合模型(GMM)中的应用

    1. EM算法的基本思想 我们在应用中所面对的数据有时是缺损的/观测不完全的[1][2].我们将数据分为: 可观测数据,用\(Y\)表示: 缺失数据,用\(Z\)表示; 完全数据,用\(X=(Y, Z ...

  5. 如何在多个 Git 平台玩转一个仓库

    版本控制在软件开发中至关重要,而 Git 是广泛使用的代码管理工具.有时,我们可能需要在多个平台 (如 GitHub.GitLab 和 Gitee) 上同步同一 Git 仓库,以便备份.协作等. 本文 ...

  6. vue-cli 中使用 Axios

    安装 axios: 1 npm install axios --save-dev 接着在src目录下创建一个http.js脚本中,导入axios并通过create方法实例化一个http请求对象,这样我 ...

  7. Vue——Ajax请求的基本使用

    1.get方法发送Ajax请求 // 直接在 URL 上添加参数 ID=12345 axios.get('/user?ID=12345') .then(function (response) { co ...

  8. 新手入门html

    网页的组成:结构 表现 行为 Web标准: 结构  表现 行为 Html  css  js Html和css 是w3c制定标准  js是ECMA制定标准 HTML:指的是超文本标记语言 文件命名的规范 ...

  9. kettle从入门到精通 第十六课 kettle 映射 (子转换)02

    1.上节讲的子映射里面只有一个转换(类似一个java类里面只有一个公共方法),本次讲解的有两个,实际上可以有任意多个(一个java类里面有多个公共方法).两个转换分别计算x+y和x*y. 2.命名参数 ...

  10. 大量索引场景下 Easysearch 和 Elasticsearch 的吞吐量差异

    最近有客户在使用 Elasticsearch 搜索服务时发现集群有掉节点,并且有 master 收集节点信息超时的日志,节点的负载也很高,不只是 data 节点,master 和协调节点的 cpu 使 ...