egg-view
Version:
Base view plugin for egg
289 lines (217 loc) • 7.16 kB
Markdown
# egg-view
[![NPM version][npm-image]][npm-url]
[![build status][travis-image]][travis-url]
[![Test coverage][codecov-image]][codecov-url]
[![David deps][david-image]][david-url]
[![Known Vulnerabilities][snyk-image]][snyk-url]
[![npm download][download-image]][download-url]
[npm-image]: https://img.shields.io/npm/v/egg-view.svg?style=flat-square
[npm-url]: https://npmjs.org/package/egg-view
[travis-image]: https://img.shields.io/travis/eggjs/egg-view.svg?style=flat-square
[travis-url]: https://travis-ci.org/eggjs/egg-view
[codecov-image]: https://img.shields.io/codecov/c/github/eggjs/egg-view.svg?style=flat-square
[codecov-url]: https://codecov.io/github/eggjs/egg-view?branch=master
[david-image]: https://img.shields.io/david/eggjs/egg-view.svg?style=flat-square
[david-url]: https://david-dm.org/eggjs/egg-view
[snyk-image]: https://snyk.io/test/npm/egg-view/badge.svg?style=flat-square
[snyk-url]: https://snyk.io/test/npm/egg-view
[download-image]: https://img.shields.io/npm/dm/egg-view.svg?style=flat-square
[download-url]: https://npmjs.org/package/egg-view
Base view plugin for egg
**it's a plugin that has been built-in for egg.**
## Install
```bash
$ npm i egg-view --save
```
## Usage
```js
// {app_root}/config/plugin.js
exports.view = {
enable: true,
package: 'egg-view',
};
```
## Use a template engine
[egg-view] don't have build-in view engine, So you should choose a template engine like [ejs], and install [egg-view-ejs] plugin.
You can choose a template engine first, link [ejs], so we use [egg-view-ejs] plugin.
`egg-view` is in [eggjs], so you just need configure [egg-view-ejs].
```js
// config/plugin.js
exports.ejs = {
enable: true,
package: 'egg-view-ejs',
};
```
Configure the mapping, the file with `.ejs` extension will be rendered by ejs.
```js
// config/config.default.js
exports.view = {
mapping: {
'.ejs': 'ejs',
},
};
```
In controller, you can call `ctx.render`.
```js
module.exports = app => {
return class UserController extends app.Controller {
async list() {
const { ctx } = this;
await ctx.render('user.ejs');
}
};
};
```
If you call `ctx.renderString`, you should specify viewEngine in viewOptions.
```js
module.exports = app => {
return class UserController extends app.Controller {
async list() {
const { ctx } = this;
ctx.body = await ctx.renderString('<%= user %>', { user: 'popomore' }, {
viewEngine: 'ejs',
});
}
};
};
```
## Use multiple view engine
[egg-view] support multiple view engine, so you can use more than one template engine in one application.
If you want add another template engine like [nunjucks], then you can add [egg-view-nunjucks] plugin.
Configure the plugin and mapping
```js
// config/config.default.js
exports.view = {
mapping: {
'.ejs': 'ejs',
'.nj': 'nunjucks',
},
};
```
You can simply render the file with `.nj` extension.
```js
await ctx.render('user.nj');
```
## How to write a view plugin
You can use [egg-view]' API to register a plugin.
### View engine
Create a view engine class first, and implement `render` and `renderString`, if the template engine don't support, just throw an error. The view engine is context level, so it receive ctx in `constructor`.
```js
// lib/view.js
module.exports = class MyView {
constructor(ctx) {
// do some initialize
// get the plugin config from `ctx.app.config`
}
async render(fullpath, locals) {
return myengine.render(fullpath, locals);
}
async renderString() { throw new Error('not implement'); }
};
```
`render` and `renderString` support generator function, async function, or normal function return a promise.
If the template engine only support callback, you can wrap it by Promise.
```js
class MyView {
render(fullpath, locals) {
return new Promise((resolve, reject) => {
myengine.render(fullpath, locals, (err, result) => {
if (err) {
reject(err);
} else {
resolve(result);
}
});
});
}
};
```
These methods receive three arguments, `renderString` will pass tpl as the first argument instead of name in `render`.
`render(name, locals, viewOptions)`
- name: the file path that can resolve from root (`app/view` by default)
- locals: data used by template
- viewOptions: the view options for each render, it can override the view default config in `config/config.default.js`. Plugin should implement it if it has config.
When you implement view engine, you will receive this options from `render`, the options contain:
- root: egg-view will resolve the name to full path, but seperating root and name in viewOptions.
- name: the original name when call render
`renderString(tpl, locals, viewOptions)`
- tpl: the template string instead of the file, using in `renderString`
- locals: same as `render`
- viewOptions: same as `render`
### Register
After define a view engine, you can register it.
```js
// app.js
module.exports = app => {
app.view.use('myName', require('./lib/view'));
};
```
You can define a view engine name, normally it's a template name.
### Configure
Define plugin name and depend on [egg-view]
```json
{
"eggPlugin": {
"name": "myName",
"dependencies": [ "view" ]
}
}
```
Set default config in `config/config.default.js`, the name is equals to plugin name.
```js
exports.myName = {},
```
See some examples
- [egg-view-ejs]
- [egg-view-nunjucks]
## Configuration
### Root
Root is `${baseDir}/app/view` by default, but you can define multiple directory, seperated by `,`. [egg-view] will find a file from all root directories.
```js
module.exports = appInfo => {
const baseDir = appInfo.baseDir;
return {
view: {
root: `${baseDir}/app/view,${baseDir}/app/view2`
}
}
}
```
### defaultExtension
When render a file, you should specify a extension that let [egg-view] know whitch engine you want to use. However you can define `defaultExtension` without write the extension.
```js
// config/config.default.js
exports.view = {
defaultExtension: '.html',
};
// controller
module.exports = app => {
return class UserController extends app.Controller {
async list() {
const { ctx } = this;
// render user.html
await ctx.render('user');
}
};
};
```
### viewEngine and defaultViewEngine
If you are using `renderString`, you should specify viewEngine in view config, see example above.
However, you can define `defaultViewEngine` without set each time.
```js
// config/config.default.js
exports.view = {
defaultViewEngine: 'ejs',
};
```
see [config/config.default.js](https://github.com/eggjs/egg-view/blob/master/config/config.default.js) for more detail.
## Questions & Suggestions
Please open an issue [here](https://github.com/eggjs/egg/issues).
## License
[MIT](https://github.com/eggjs/egg-view/blob/master/LICENSE)
[eggjs]: https://eggjs.org
[ejs]: https://github.com/mde/ejs
[egg-view-ejs]: https://github.com/eggjs/egg-view-ejs
[egg-view]: https://github.com/eggjs/egg-view
[nunjucks]: http://mozilla.github.io/nunjucks
[egg-view-nunjucks]: https://github.com/eggjs/egg-view-nunjucks