使用Nunjucks
Nunjucks
Nunjucks是什么东东?其实它是一个模板引擎。
那什么是模板引擎?
模板引擎就是基于模板配合数据构造出字符串输出的一个组件。比如下面的函数就是一个模板引擎:
function examResult (data) {return `${data.name}同学一年级期末考试语文${data.chinese}分,数学${data.math}分,位于年级第${data.ranking}名。`
}
如果我们输入数据如下:
examResult({name: '小明',chinese: 78,math: 87,ranking: 999
});
该模板引擎把模板字符串里面对应的变量替换以后,就可以得到以下输出:
小明同学一年级期末考试语文78分,数学87分,位于年级第999名。
模板引擎最常见的输出就是输出网页,也就是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) {varautoescape = 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', {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;
}var env = createEnv('views', {watch: true,filters: {hex: function (n) {return '0x' + n.toString(16);}}
});
变量env
就表示Nunjucks模板引擎对象,它有一个render(view, model)
方法,正好传入view
和model
两个参数,并返回字符串。
创建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 <script>alert("小明")</script></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
定义了三个可编辑的块,分别命名为header
、body
和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的性能。
对于模板渲染本身来说,速度是非常非常快的,因为就是拼字符串嘛,纯CPU操作。
性能问题主要出现在从文件读取模板内容这一步。这是一个IO操作,在Node.js环境中,我们知道,单线程的JavaScript最不能忍受的就是同步IO,但Nunjucks默认就使用同步IO读取模板文件。
好消息是Nunjucks会缓存已读取的文件内容,也就是说,模板文件最多读取一次,就会放在内存中,后面的请求是不会再次读取文件的,只要我们指定了noCache: false
这个参数。
在开发环境下,可以关闭cache,这样每次重新加载模板,便于实时修改模板。在生产环境下,一定要打开cache,这样就不会有性能问题。
Nunjucks也提供了异步读取的方式,但是这样写起来很麻烦,有简单的写法我们就不会考虑复杂的写法。保持代码简单是可维护性的关键。
参考源码
use-nunjucks
使用Nunjucks相关推荐
- 前端模板Nunjucks简介
参考资料: https://mozilla.github.io/nunjucks/ https://mozilla.github.io/nunjucks/templating.html https:/ ...
- koa --- nunjucks在Koa中的使用、中间件的配置
Nunjucks在Koa中的应用 app.js const koa = require('koa'); const app = new koa(); const router = require('. ...
- koa --- nunjucks
安装: npm install koa-nunjucks-2 --save 目录结构 |--- controller/ | |--- home.js |--- service/ | |--- home ...
- nunjucks渲染富文本解析错误输出字符串而不是元素
今天遇到个坑,nunjucks 的插入变量{{}}输出的是字符串,而我用富文本编辑器插入数据库的是字符串,它不解析成元素(html),怎么办? 用什么方法引入它能成html? 网上查,没这个资料 因为 ...
- nunjucks.js模板渲染
直接用 script 引入文件: <script src="nunjucks.js"></script> 是使用 render 来直接渲染文件,这种方式支持 ...
- 小试牛刀之NunJucks模板引擎
NunJucks模板引擎 NunJucks中文文档 模板引擎有很多,我之前就曾用过ejs,都是对页面进行渲染.接下来带大家简单体验一下Nunjucks.真别说,插值语法有点vue的那股味道了. 初试N ...
- js模板引擎Nunjucks
js模板引擎Nunjucks Nunjucks中文文档
- thinkjs能在浏览器html文件,thinkjs框架的默认模板引擎Nunjucks的中文文档
Node 端使用 $ npm install nunjucks 0 $npminstallnunjucks 下载后可直接 require('nunjucks') 使用 浏览器端使用 可直接使用 nun ...
- Nunjucks Error: 解决方案
hexo d报错 FATAL Something's wrong. Maybe you can find the solution here: https://hexo.io/docs/trouble ...
- Nunjucks简介基本使用教程
Nunjucks简介: Nunjucks 是一个功能丰富.强大的 JavaScript 专用模板引擎.Nunjucks 提供丰富的语言特性和块继承.自动转移.宏和异步控制等等. 重点要关注的是,Nu ...
最新文章
- 解读刘强东关于人才的两个标准和5个层次
- C++非类型模板参数
- 百度ueditor编辑器动态获取项目根目录
- 通讯业2月网络广告投放环比增33% 联通居首位
- 开源Linux 3.3内核首次融合Android代码
- centos 7.9密码改密钥登陆
- 201103阶段二linux gdb调试与ftp配置
- React开发(130):ant design学习指南之form中的新城多个表单
- Fedora 10初体验
- python画六角图_六角图的画法
- vmware + ubuntu + docker+ tensorflow
- PaddlePaddle(6)—— 基于Hub Serving的微信小程序模型部署
- 分享一张牛逼的程序员职业路线图给你们!
- treemap倒叙_lua 模拟Treemap 排序
- AT91SAM7SE应用 -- UART
- 《高效阅读——20分钟读懂一本书》读书总结
- 激活硬盘被关闭的DMA模式
- Chrome(谷歌浏览器) 程序开发32个经常使用插件
- python统计英文文章中单词出现的次数
- 【算法学习笔记】65. 双向扫描 SJTU OJ 1382 畅畅的牙签盒
热门文章
- 防火墙设置入站规则和ping请求超时解决办法(Tomcat+Windows项目部署后续)
- AD17PCB 导出CAD文件
- 如何关闭华为自动杀进程_苹果产品如何关闭烦人的自动更新
- c语言 单词变复数_DEV-C++中编写了一段C程序,其中设置了用文件进行... 请编一个程序,可以将英语规则名词由单数变成复数......
- iOS CALayer之CAEmitterLayer粒子发射器的神奇效果
- k8s集群node节点运行kubectl命令
- 小程序字体font列表
- Linux 最小化安装后IP的配置(手动获取静态IP地址)
- 技嘉计算机主板排行,技嘉热门主板推荐 英特尔平台技嘉主板有哪些 哪款好-太平洋电脑网...
- 服务器被DDoS攻击了怎么办?