Koa中間件使用之koa-nunjucks-2

Koa-nunjucks-2Koa 的一個(gè)輕量級(jí) Nunjucks 中間件炼鞠,可以用來(lái)作為模板引擎强窖,為 koa 應(yīng)用提供頁(yè)面渲染功能客蹋。

那么,koa-nunjucks-2 做了什么?

  1. 通過(guò)創(chuàng)建 koa-nunjucks-2 實(shí)例會(huì)返回一個(gè)中間件,使用這個(gè)中間件會(huì)讓上下文獲得一個(gè)渲染方法;
  2. 從渲染方法參數(shù)上獲取傳遞的數(shù)據(jù)(其次從 ctx.state 獲燃燎拧),然后使用 nunjucks 渲染模板百姓;
  3. 根據(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>

更多的使用這里不再列舉,可以查看官方的文檔碴犬。

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末絮宁,一起剝皮案震驚了整個(gè)濱河市,隨后出現(xiàn)的幾起案子服协,更是在濱河造成了極大的恐慌绍昂,老刑警劉巖,帶你破解...
    沈念sama閱讀 219,490評(píng)論 6 508
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件蚯涮,死亡現(xiàn)場(chǎng)離奇詭異治专,居然都是意外死亡,警方通過(guò)查閱死者的電腦和手機(jī)遭顶,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 93,581評(píng)論 3 395
  • 文/潘曉璐 我一進(jìn)店門(mén)首有,熙熙樓的掌柜王于貴愁眉苦臉地迎上來(lái),“玉大人磨总,你說(shuō)我怎么就攤上這事皮壁。” “怎么了铣揉?”我有些...
    開(kāi)封第一講書(shū)人閱讀 165,830評(píng)論 0 356
  • 文/不壞的土叔 我叫張陵饶深,是天一觀的道長(zhǎng)。 經(jīng)常有香客問(wèn)我逛拱,道長(zhǎng)敌厘,這世上最難降的妖魔是什么? 我笑而不...
    開(kāi)封第一講書(shū)人閱讀 58,957評(píng)論 1 295
  • 正文 為了忘掉前任朽合,我火速辦了婚禮俱两,結(jié)果婚禮上饱狂,老公的妹妹穿的比我還像新娘。我一直安慰自己宪彩,他們只是感情好休讳,可當(dāng)我...
    茶點(diǎn)故事閱讀 67,974評(píng)論 6 393
  • 文/花漫 我一把揭開(kāi)白布。 她就那樣靜靜地躺著尿孔,像睡著了一般俊柔。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上活合,一...
    開(kāi)封第一講書(shū)人閱讀 51,754評(píng)論 1 307
  • 那天雏婶,我揣著相機(jī)與錄音,去河邊找鬼芜辕。 笑死尚骄,一個(gè)胖子當(dāng)著我的面吹牛,可吹牛的內(nèi)容都是我干的侵续。 我是一名探鬼主播倔丈,決...
    沈念sama閱讀 40,464評(píng)論 3 420
  • 文/蒼蘭香墨 我猛地睜開(kāi)眼,長(zhǎng)吁一口氣:“原來(lái)是場(chǎng)噩夢(mèng)啊……” “哼状蜗!你這毒婦竟也來(lái)了需五?” 一聲冷哼從身側(cè)響起,我...
    開(kāi)封第一講書(shū)人閱讀 39,357評(píng)論 0 276
  • 序言:老撾萬(wàn)榮一對(duì)情侶失蹤轧坎,失蹤者是張志新(化名)和其女友劉穎宏邮,沒(méi)想到半個(gè)月后,有當(dāng)?shù)厝嗽跇?shù)林里發(fā)現(xiàn)了一具尸體缸血,經(jīng)...
    沈念sama閱讀 45,847評(píng)論 1 317
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡蜜氨,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 37,995評(píng)論 3 338
  • 正文 我和宋清朗相戀三年,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了捎泻。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片飒炎。...
    茶點(diǎn)故事閱讀 40,137評(píng)論 1 351
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡,死狀恐怖笆豁,靈堂內(nèi)的尸體忽然破棺而出郎汪,到底是詐尸還是另有隱情,我是刑警寧澤闯狱,帶...
    沈念sama閱讀 35,819評(píng)論 5 346
  • 正文 年R本政府宣布煞赢,位于F島的核電站,受9級(jí)特大地震影響哄孤,放射性物質(zhì)發(fā)生泄漏照筑。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 41,482評(píng)論 3 331
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望凝危。 院中可真熱鬧饭弓,春花似錦、人聲如沸媒抠。這莊子的主人今日做“春日...
    開(kāi)封第一講書(shū)人閱讀 32,023評(píng)論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽(yáng)趴生。三九已至,卻和暖如春昏翰,著一層夾襖步出監(jiān)牢的瞬間苍匆,已是汗流浹背。 一陣腳步聲響...
    開(kāi)封第一講書(shū)人閱讀 33,149評(píng)論 1 272
  • 我被黑心中介騙來(lái)泰國(guó)打工棚菊, 沒(méi)想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留浸踩,地道東北人。 一個(gè)月前我還...
    沈念sama閱讀 48,409評(píng)論 3 373
  • 正文 我出身青樓统求,卻偏偏與公主長(zhǎng)得像检碗,于是被迫代替她去往敵國(guó)和親。 傳聞我的和親對(duì)象是個(gè)殘疾皇子码邻,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 45,086評(píng)論 2 355