eggjs里,采用的是MVC模式,页面访问流程大概是:浏览器输入地址 ==>进入路由 ==> 进入指定的控制器(controller
) ==>通过数据模板(model
)查询数据 ==>把数据注入到模板(view
)里渲染 ==>返回给浏览器显示。
通常,我们会为单个页面需要的数据,在控制器里查询出来,然后丢给模板渲染的。但有一些变量,是涉及到每个页面都需要显示的情况,譬如导航栏里的菜单,或者侧边栏里的分类列表,用户基本信息等。如果在每个控制器里,都查一遍再注入到模板,那就很费代码量了。
作为一个成熟的框架,eggjs当然也有自己的解决方案。
我们可以采用:中间件 + ctx.locals 来解决。
第一步:写一个中间件
在app/middleware里,新建文件:localsHandler.js,
譬如我们把文章分类注入到每个页面:
'use strict';
module.exports = () => {
return async function localsHandler(ctx, next) {
// 通过locals注入到模板
const categoryList = await ctx.model.Articlecategory.findAll();
ctx.locals.categoryList = categoryList;
await next();
};
};
第二步:在config里使用中间件
找到 config/config.default.js
config.middleware = [ 'localsHandler' ];
第三步:在模板里输出测试变量
eggjs一般采用nunjucks
,或者ejs
作为模板引擎,我这里使用ejs
<!-- vuews/home.ejs -->
<!DOCTYPE html>
<html lang="en">
<head>
<%- include('common/head'); -%>
</head>
<body>
<% categoryList.forEach(function(item){ %>
<p><%= item.name %></p>
<% }); %>
</body>
</html>
就这样,我们就可以把全局用到的变量,在localsHandler中间件里查询出来,然后注入到locals变量。这样就可以在任意模板里使用这些变量,而避免在每一个控制器里重复做查询了。