View 模板渲染
绝大多数情况,我们都需要读取数据后渲染模板,然后呈现给用户。故我们需要引入对应的模板引擎。
框架内置 egg-view 作为模板解决方案,并支持多模板渲染,每个模板引擎都以插件的方式引入,但保持渲染的 API 一致。如果想更深入的了解,可以查看模板插件开发。
以下以官方支持的 View 插件 egg-view-nunjucks 为例
# 引入 view 插件
$ npm i egg-view-nunjucks --save |
# 启用插件
// config/plugin.js |
# 配置插件
egg-view 提供了 config.view
通用配置
# root {String}
模板文件的根目录,为绝对路径,默认为 ${baseDir}/app/view
。支持配置多个目录,以 ,
分割,会从多个目录查找文件。
如下示例演示了如何配置多个 view
目录:
// config/config.default.js |
# cache {Boolean}
模板路径缓存,默认开启。框架会根据 root 配置的目录依次查找,如果匹配则会缓存文件路径,下次渲染相同路径时不会重新查找。
# mapping 和 defaultViewEngine
每个模板在注册时都会指定一个模板名(viewEngineName),在使用时需要根据后缀来匹配模板名,比如指定 .nj
后缀的文件使用 Nunjucks 进行渲染。
module.exports = { |
调用 render 渲染文件时,会根据上述配置的后缀名去寻找对应的模板引擎。
await ctx.render('home.nj'); |
必须配置文件后缀和模板引擎的映射,否则无法找到对应的模板引擎,但是可以使用 defaultViewEngine
做全局配置。
// config/config.default.js |
如果根据文件后缀没有找到对应的模板引擎,会使用默认的模板引擎进行渲染。对于只使用一种模板引擎的应用,建议配置此选项。
# defaultExtension
一般在调用 render 时的第一个参数需要包含文件后缀,如果配置了 defaultExtension 可以省略后缀。
// config/config.default.js |
# 渲染页面
框架在 Context 上提供了 3 个接口,返回值均为 Promise:
render(name, locals)
渲染模板文件, 并赋值给 ctx.bodyrenderView(name, locals)
渲染模板文件, 仅返回不赋值renderString(tpl, locals)
渲染模板字符串, 仅返回不赋值
// {app_root}/app/controller/home.js |
当使用 renderString
时需要指定模板引擎,如果已经定义 defaultViewEngine
这里可以省略。
# Locals
在渲染页面的过程中,我们通常需要一个变量来收集需要传递给模板的变量,在框架里面,我们提供了 app.locals
和 ctx.locals
。
app.locals
为全局的,一般在app.js
里面配置全局变量。ctx.locals
为单次请求的,会合并app.locals
。- 可以直接赋值对象,框架在对应的 setter 里面会自动 merge。
// `app.locals` 会合并到 `ctx.locals |
但在实际业务开发中,controller 中一般不会直接使用这 2 个对象,直接使用 ctx.render(name, data)
即可:
- 框架会自动把
data
合并到ctx.locals
。 - 框架会自动注入
ctx
,request
,helper
方便使用。
ctx.app.locals = { appName: 'showcase' }; |
注意:
- ctx.locals 有缓存,只在第一次访问 ctx.locals 时合并 app.locals。
- 原 Koa 中的
ctx.state
,由于容易产生歧义,在框架中被覆盖为 locals,即ctx.state
和ctx.locals
等价,我们建议使用后者。
# Helper
在模板中可以直接使用 helper
上注册的方法,具体可以参见扩展。
// app/extend/helper.js |
# Security
框架内置的 egg-security 插件,为我们提供了常见的安全辅助函数,包括 helper.shtml / surl / sjs
等等等,强烈建议阅读下安全。