Koa-nunjucks-2 是 Koa 的一個(gè)輕量級(jí) Nunjucks 中間件炼鞠,可以用來(lái)作為模板引擎强窖,為 koa 應(yīng)用提供頁(yè)面渲染功能客蹋。
那么,koa-nunjucks-2 做了什么?
- 通過(guò)創(chuàng)建
koa-nunjucks-2
實(shí)例會(huì)返回一個(gè)中間件,使用這個(gè)中間件會(huì)讓上下文獲得一個(gè)渲染方法; - 從渲染方法參數(shù)上獲取傳遞的數(shù)據(jù)(其次從
ctx.state
獲燃燎拧),然后使用 nunjucks 渲染模板百姓; - 根據(jù)用戶配置決定是否返回HTML頁(yè)面渊额。
可以參考從源碼里面截取的片段,如下:
const env = nunjucks.configure(config.path, config.nunjucksConfig);
env.renderAsync = bluebird.promisify(env.render);
return async (ctx, next) => {
if (ctx[config.functionName]) {
throw new Error(`ctx.${config.functionName} is already defined`);
}
/**
* @param {string} view
* @param {!Object=} context
* @returns {string}
*/
ctx[config.functionName] = async (view, context) => {
const mergedContext = merge({}, ctx.state, context);
view += config.ext;
return env.renderAsync(view, mergedContext)
.then((html) => {
if (config.writeResponse) {
ctx.type = 'html';
ctx.body = html;
}
});
};
await next();
};
從上面的代碼可以看出垒拢,在創(chuàng)建 koa-nunjucks-2 中間件時(shí)旬迹,可以傳遞文件后綴 ext
,渲染方法名 functionName
求类,以及 nunjucks 的配置信息 nunjucksConfig
等奔垦。
基本配置
創(chuàng)建Koa應(yīng)用
下面的代碼創(chuàng)建了一個(gè)koa web服務(wù),監(jiān)聽(tīng)了3000端口尸疆,如果訪問(wèn) http://localhost:3000/ 將返回 Not Found
椿猎,這是因?yàn)榇a沒(méi)有對(duì)請(qǐng)求做任何響應(yīng)。后面將使用 koa-nunjucks-2 在這個(gè)基礎(chǔ)上進(jìn)行修改寿弱,使其支持渲染頁(yè)面犯眠。
// app.js
const Koa = require('koa'); // 引入koa
const app = new Koa(); // 創(chuàng)建koa應(yīng)用
// 啟動(dòng)服務(wù)監(jiān)聽(tīng)本地3000端口
app.listen(3000, () => {
console.log('應(yīng)用已經(jīng)啟動(dòng),http://localhost:3000');
})
安裝 koa-nunjucks-2
$ npm install koa-nunjucks-2 --save
使用 koa-nunjucks-2
首先症革,使用 require()
引入 koa-nunjucks-2
筐咧,并且對(duì)其實(shí)例化(支持傳遞參數(shù)),然后會(huì)獲得一個(gè)中間件噪矛。并且調(diào)用 app.use()
使用這個(gè)中間件:
const Koa = require('koa'); // 引入koa
const koaNunjucks = require('koa-nunjucks-2'); // 引入 koa-nunjucks-2
const path = require('path');
const app = new Koa(); // 創(chuàng)建koa應(yīng)用
// 使用 koa-nunjucks-2 實(shí)例獲得中間件
app.use(koaNunjucks({
ext: 'html', // 使用HTML后綴的模板
path: path.join(__dirname, 'view'), // 模板所在路徑
nunjucksConfig: { // nunjucks的配置
trimBlocks: true
}
}));
// 啟動(dòng)服務(wù)監(jiān)聽(tīng)本地3000端口
app.listen(3000, () => {
console.log('應(yīng)用已經(jīng)啟動(dòng)量蕊,http://localhost:3000');
})
配置好 koa-nunjucks-2
中間件之后,它默認(rèn)會(huì)在請(qǐng)求上下文(context)上增加 render()
方法艇挨,通過(guò)調(diào)用 ctx.render('模板名', 數(shù)據(jù))
就可以渲染頁(yè)面残炮,比如下面代碼:
// app.js
const Koa = require('koa'); // 引入koa
const koaNunjucks = require('koa-nunjucks-2'); // 引入 koa-nunjucks-2
const path = require('path');
const app = new Koa(); // 創(chuàng)建koa應(yīng)用
// 使用 koa-nunjucks-2 實(shí)例獲得中間件
app.use(koaNunjucks({
ext: 'html', // 使用HTML后綴的模板
path: path.join(__dirname, 'view'), // 模板所在路徑
nunjucksConfig: { // nunjucks的配置
trimBlocks: true
}
}));
+ app.use(async ctx => {
+ await ctx.render('index', { text: 'Hello World!' }); // 使用 ctx.render 可以通過(guò) + nunjucks 渲染頁(yè)面
+ })
// 啟動(dòng)服務(wù)監(jiān)聽(tīng)本地3000端口
app.listen(3000, () => {
console.log('應(yīng)用已經(jīng)啟動(dòng),http://localhost:3000');
})
模板里面的代碼如下:
<!-- view/index.html -->
<h1>
{{ text }}
</h1>
在調(diào)用 ctx.render
時(shí)傳遞的數(shù)據(jù)可以在模板里面通過(guò)插值表達(dá)式的形式 {{ text }}
渲染出來(lái)缩滨,可以訪問(wèn) http://localhost:3000/ 進(jìn)行確認(rèn)势就。
配合 koa-router 使用
關(guān)于 koa-router 的使用可以參考這里:Koa中間件使用之koa-router ,這里使用 koa-router 來(lái)匹配路徑脉漏,從而達(dá)到渲染不同頁(yè)面的目的苞冯。
先來(lái)在代碼里面加入 koa-router
:
// app.js
// ...
+ const Router = require('koa-router');
const app = new Koa(); // 創(chuàng)建koa應(yīng)用
+ const router = new Router();
// 使用 koa-nunjucks-2 實(shí)例獲得中間件
app.use(koaNunjucks({
ext: 'html', // 使用HTML后綴的模板
path: path.join(__dirname, 'view'), // 模板所在路徑
nunjucksConfig: { // nunjucks的配置
trimBlocks: true
}
}));
- app.use(async ctx => {
+ router.get('/', async ctx => {
await ctx.render('index', { text: 'Hello World!' }); // 使用 ctx.render 可以通過(guò) nunjucks 渲染頁(yè)面
})
+ app.use(router.routes()).use(router.allowedMethods());
// 啟動(dòng)服務(wù)監(jiān)聽(tīng)本地3000端口
app.listen(3000, () => {
console.log('應(yīng)用已經(jīng)啟動(dòng),http://localhost:3000');
})
上面的代碼中鸠删, app.use(nunjucks({}))
放在 app.use(router.routes()).use(router.allowedMethods())
前面才行,否則會(huì)報(bào) ctx.render()
不是一個(gè) function
贼陶。
Nunjucks使用
這里指列舉一些使用方法刃泡,具體可以參考 nunjucks 的文檔 巧娱。
變量
變量會(huì)從模板上下文獲取,如果你想顯示一個(gè)變量可以:
{{ username }}
會(huì)從上下文查找 username
然后顯示烘贴,可以像 javascript 一樣獲取變量的屬性:
{{ foo.bar }}
{{ foo["bar"] }}
過(guò)濾器
過(guò)濾器是一些可以執(zhí)行變量的函數(shù)禁添,通過(guò)管道操作符 (|
) 調(diào)用,并可接受參數(shù)桨踪。
{{ foo | title }}
{{ foo | join(",") }}
{{ foo | replace("foo", "bar") | capitalize }}
第三個(gè)例子展示了鏈?zhǔn)竭^(guò)濾器老翘,最終會(huì)顯示 "Bar",第一個(gè)過(guò)濾器將 "foo" 替換成 "bar"锻离,第二個(gè)過(guò)濾器將首字母大寫(xiě)铺峭。
Nunjucks 提供了一些內(nèi)置的過(guò)濾器,你也可以自定義過(guò)濾器汽纠。
if
if
為分支語(yǔ)句卫键,與 javascript 中的 if
類似。
{% if variable %}
It is true
{% endif %}
如果 variable
定義了并且為真值虱朵。
{% if hungry %}
I am hungry
{% elif tired %}
I am tired
{% else %}
I am good!
{% endif %}
for
for
可以遍歷數(shù)組 (arrays) 和對(duì)象 (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>
更多的使用這里不再列舉,可以查看官方的文檔碴犬。