node的express默认的模板引擎是ejs和jade,jade的难度最高,初学者很容易会少写空格等从而导致编译失败,而ejs语法和js类似,使用起来更加顺手,nunjucks的写法和ejs相似,但是功能要比ejs强大,简单的介绍一下nunjucks的使用。
nunjucks官方文档有中文版,详细的文档请移步 Nunjucks 。这里我就写一下简单的使用,适合入门开发者学习。
安装
npm install nunjucks --save
开始使用
var nunjucks = require('nunjucks'); //nunjucks.configure([path], [opts]) nunjucks.configure(['views','onlineview'],{ autoescape:true,//控制输出是否被转义 express:app,//传入 express 实例初始化模板设置 });
configure
nunjucks.configure([path], [opts]);
传入 path 指定存放模板的目录,opts 可让某些功能开启或关闭,这两个变量都是可选的。path 的默认值为当前的工作目录,opts 提供以下功能:
- autoescape (默认值: true) 控制输出是否被转义,查看 Autoescaping
- throwOnUndefined (default: false) 当输出为 null 或 undefined 会抛出异常
- trimBlocks (default: false) 自动去除 block/tag 后面的换行符
- lstripBlocks (default: false) 自动去除 block/tag 签名的空格
- watch (默认值: false) 当模板变化时重新加载。使用前请确保已安装可选依赖 chokidar。
- noCache (default: false) 不使用缓存,每次都重新编译
- web 浏览器模块的配置项
- useCache (default: false) 是否使用缓存,否则会重新请求下载模板
- async (default: false) 是否使用 ajax 异步下载模板
- express 传入 express 实例初始化模板设置
- tags: (默认值: see nunjucks syntax) 定义模板语法,查看 Customizing Syntax
configure 返回一个 Environment 实例, 他提供了简单的 api 添加过滤器 (filters) 和扩展 (extensions),可在 Environment 查看更多的使用方法。
注意: 简单的API (比如说上面的nunjucks.render) 通常会使用最近一次调用nunjucks.configure时的配置。由于这种做法是隐性的,它可能会渲染出意料之外的结果,所以在大多数情况下我们不推荐使用这类简单的API(特别是用到configure的情况);我们推荐使用var env = nunjucks.configure(...)创建一个独立的环境,并调用env.render(...)进行渲染。
简单的例子:
//server.js var express = require('express'); var app = express(); var nunjucks = require('nunjucks') var env = nunjucks.configure(['views','view2'],{ autoescape:true, express:app, watch:true }); app.get('/', function(req, res) { res.render('index.html',{ appTitle:'这是app Title', css:'这是css文件', js:'<script src="server.js"></script>' }); }); app.listen('5525',function () { console.log('5525测试'); })
views/index.html
<!DOCTYPE html> <html> <head> <title> </title> </head> <body> <h1> {{appTitle}} </h1> {% if css%} <h2>有css</h2> <p>{{css}}</p> {% endif%} {% if js%} {{js}} {% endif %} </body> </html>
预览效果:
以上是最简单的实现方式,但是我们在项目中可能会用到一些继承复用等。
继承
继承功能会使用到extends 和 block标签 。
parent.html
<!DOCTYPE html> <html> <head> <title> </title> </head> <body> <h1> {% block title%}{% endblock%} </h1> <p>{% block content%} {% endblock %}</p> </body> </html>
index.html
{% extends "parent.html" %} {% block title%} 这个是父模板的title{% endblock %} {% block content%} 这个是父模板的content {% endblock %}
效果:
这是最简单的继承写法
super
你可以通过调用super
从而将父级区块中的内容渲染到子区块中。
parent.html
{% block title%} --这个是父模板原来-- {% endblock%}
index.html
{% extends "parent.html" %} {% block title%} {{super()}}这个是父模板的title{% endblock %} {% block content%} 这个是父模板的content {% endblock %}
这样就可以显示两个字符串
--这个是父模板原来-- 这个是父模板的title
自定义
if
if
为分支语句,与 javascript 中的 if
类似。
{% if title %} It is true {% endif %}
如果title定义了并且为true,就执行当中的代码
for
for
可以遍历数组 (arrays) 和对象 (dictionaries)。
var items = [{ title: "foo", id: 1 }, { title: "bar", id: 2}];
<h1>Posts</h1> <ul> {% for item in items %} <li>{{ item.title }}</li> {% else %} <li>This would display if the 'item' collection were empty</li> {% endfor %} </ul>
上面的示例通过使用items
数组中的每一项的title
属性显示了所有文章的标题。如果items
数组是空数组的话则会渲染else
语句中的内容。
你还可以遍历对象:
var food = { 'ketchup': '5 tbsp', 'mustard': '1 tbsp', 'pickle': '0 tbsp' };
{% for ingredient, amount in food %} Use {{ amount }} of {{ ingredient }} {% endfor %}
dictsort
过滤器可将对象排序 (new in 0.1.8)
set
set
可以设置和修改变量。
{{ username }} {% set username = "joe" %} {{ username }}
如果 username
初始化的时候为 "james', 最终将显示 "james joe"。
可以设置新的变量,并一起赋值。
{% set x, y, z = 5 %}
如果在顶级作用域使用 set
,将会改变全局的上下文中的值。如果只在某个作用域 (像是include或是macro) 中使用,则只会影响该作用域。
同样地,你也可以使用区块赋值将一个区块的内容储存在一个变量中。
它的语法和标准的set
语法相似,只不过你不需要用=
。区块中从头到{% endset %}
之间的内容都会被捕获,并作为值来使用。
在某些情境下,你可以用这种语法来替代宏:
{% set standardModal %} {% include 'standardModalData.html' %} {% endset %} <div class="js-modal" data-modal="{{standardModal | e}}">
extends
extends
用来指定模板继承,被指定的模板为父级模板,查看模板继承。
{% extends "base.html" %}
你可以将继承的模板设为一个变量,这样就可以动态指定继承的模板。这个变量既可以是个指向模板文件的字符串,也可以是个模板编译后所生成的对象(需要添加上下文环境)。因此你可以通过设置上下文变量,从而在渲染时动态地改变所要继承的模板。
{% extends parentTemplate %}
extends
也可以接受任意表达式,只要它最终返回一个字符串或是模板所编译成的对象:
{% extends name + ".html" %}
block
区块(block
) 定义了模板片段并标识一个名字,在模板继承中使用。父级模板可指定一个区块,子模板覆盖这个区块,查看模板继承。
{% block css %} <link rel="stylesheet" href="app.css" /> {% endblock %}
可以在循环中定义区块
{% for item in items %} {% block item %}{{ item }}{% endblock %} {% endfor %}
子模板可以覆盖 item
区块并改变里面的内容。
{% extends "item.html" %} {% block item %} The name of the item is: {{ item.name }} {% endblock %}
在区块中,你可以调用特殊的super
函数。它会渲染父级区块中的内容。具体请查看super。
include
include
可引入其他的模板,可以在多模板之间共享一些小模板,如果某个模板已使用了继承那么 include
将会非常有用。
{% include "item.html" %}
这一点可以帮助我们把模板切分成更小的部分,从而使得在浏览器上,当我们需要改变页面时,我们可以渲染这些小部分的模板,而非一整个的大的模板。
include
可以接受任意表达式,只要它最终返回一个字符串或是模板所编译成的对象: {% include name + ".html" as obj %}
.
在某些情况下,我们可能希望在模板文件不存在时不要抛出异常。对于这类情况,我们可以使用ignore missing
来略过这些异常:
{% include "missing.html" ignore missing %}
被包含的模版自身可以扩展(extends
)另一个模版(因此你可以让一系列相关联的模版继承同一种结构)。 一个被包含的模版并不会改变包含它的模版的区块结构,它有一个分离的继承树和块级命名空间。换言之, 在渲染时,include
并不 不是 将被包含模版代码拉取到包含它的模版中的预处理器。相对的,它对被 包含的模版触发了一次的分离渲染,然后再将渲染的结果引入。
其他具体操作请查看官网(官网的样式写的真渣渣)
文章评论