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

Koa-nunjucks-2Koa 的一个轻量级 Nunjucks 中间件,可以用来作为模板引擎,为 koa 应用提供页面渲染功能。

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

  1. 通过创建 koa-nunjucks-2 实例会返回一个中间件,使用这个中间件会让上下文获得一个渲染方法;
  2. 从渲染方法参数上获取传递的数据(其次从 ctx.state 获取),然后使用 nunjucks 渲染模板;
  3. 根据用户配置决定是否返回HTML页面。

可以参考从源码里面截取的片段,如下:

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();
  };

从上面的代码可以看出,在创建 koa-nunjucks-2 中间件时,可以传递文件后缀 ext ,渲染方法名 functionName ,以及 nunjucks 的配置信息 nunjucksConfig 等。

基本配置

创建Koa应用

下面的代码创建了一个koa web服务,监听了3000端口,如果访问 http://localhost:3000/ 将返回 Not Found ,这是因为代码没有对请求做任何响应。后面将使用 koa-nunjucks-2 在这个基础上进行修改,使其支持渲染页面。

// app.js

const Koa = require('koa'); // 引入koa

const app = new Koa(); // 创建koa应用

// 启动服务监听本地3000端口
app.listen(3000, () => {
    console.log('应用已经启动,http://localhost:3000');
})

安装 koa-nunjucks-2

$ npm install koa-nunjucks-2 --save

使用 koa-nunjucks-2

首先,使用 require() 引入 koa-nunjucks-2 ,并且对其实例化(支持传递参数),然后会获得一个中间件。并且调用 app.use() 使用这个中间件:

const Koa = require('koa'); // 引入koa
const koaNunjucks = require('koa-nunjucks-2'); // 引入 koa-nunjucks-2
const path = require('path');

const app = new Koa(); // 创建koa应用

// 使用 koa-nunjucks-2 实例获得中间件
app.use(koaNunjucks({
    ext: 'html', // 使用HTML后缀的模板
    path: path.join(__dirname, 'view'), // 模板所在路径
    nunjucksConfig: { // nunjucks的配置
        trimBlocks: true
    }
}));

// 启动服务监听本地3000端口
app.listen(3000, () => {
    console.log('应用已经启动,http://localhost:3000');
})

配置好 koa-nunjucks-2 中间件之后,它默认会在请求上下文(context)上增加 render() 方法,通过调用 ctx.render('模板名', 数据) 就可以渲染页面,比如下面代码:

// app.js

const Koa = require('koa'); // 引入koa
const koaNunjucks = require('koa-nunjucks-2'); // 引入 koa-nunjucks-2
const path = require('path');

const app = new Koa(); // 创建koa应用

// 使用 koa-nunjucks-2 实例获得中间件
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 可以通过 + nunjucks 渲染页面
+ })

// 启动服务监听本地3000端口
app.listen(3000, () => {
    console.log('应用已经启动,http://localhost:3000');
})

模板里面的代码如下:

<!-- view/index.html -->

<h1>
    {{ text }}
</h1>

在调用 ctx.render 时传递的数据可以在模板里面通过插值表达式的形式 {{ text }} 渲染出来,可以访问 http://localhost:3000/ 进行确认。

配合 koa-router 使用

关于 koa-router 的使用可以参考这里:Koa中间件使用之koa-router ,这里使用 koa-router 来匹配路径,从而达到渲染不同页面的目的。

先来在代码里面加入 koa-router

// app.js

// ...
+ const Router = require('koa-router');

const app = new Koa(); // 创建koa应用
+ const router = new Router();

// 使用 koa-nunjucks-2 实例获得中间件
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 可以通过 nunjucks 渲染页面
})

+ app.use(router.routes()).use(router.allowedMethods());

// 启动服务监听本地3000端口
app.listen(3000, () => {
    console.log('应用已经启动,http://localhost:3000');
})

上面的代码中, app.use(nunjucks({})) 放在 app.use(router.routes()).use(router.allowedMethods()) 前面才行,否则会报 ctx.render() 不是一个 function

Nunjucks使用

这里指列举一些使用方法,具体可以参考 nunjucks 的文档

变量

变量会从模板上下文获取,如果你想显示一个变量可以:

{{ username }}

会从上下文查找 username 然后显示,可以像 javascript 一样获取变量的属性:

{{ foo.bar }}
{{ foo["bar"] }}

过滤器

过滤器是一些可以执行变量的函数,通过管道操作符 (|) 调用,并可接受参数。

{{ foo | title }}
{{ foo | join(",") }}
{{ foo | replace("foo", "bar") | capitalize }}

第三个例子展示了链式过滤器,最终会显示 "Bar",第一个过滤器将 "foo" 替换成 "bar",第二个过滤器将首字母大写。

Nunjucks 提供了一些内置的过滤器,你也可以自定义过滤器

if

if 为分支语句,与 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 可以遍历数组 (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>

更多的使用这里不再列举,可以查看官方的文档。

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 212,185评论 6 493
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 90,445评论 3 385
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 157,684评论 0 348
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 56,564评论 1 284
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 65,681评论 6 386
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 49,874评论 1 290
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 39,025评论 3 408
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 37,761评论 0 268
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 44,217评论 1 303
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 36,545评论 2 327
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 38,694评论 1 341
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 34,351评论 4 332
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 39,988评论 3 315
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 30,778评论 0 21
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 32,007评论 1 266
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 46,427评论 2 360
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 43,580评论 2 349