在 Koa 中设置全局变量并让模板引擎可以使用,通常需要以下几个步骤:
Koa 本身没有内置的模板渲染功能,通常我们会使用如 koa-views、koa-ejs、koa-nunjucks等中间件来渲染模板。这些中间件通常允许你在渲染时传入局部变量,但如果你想设置全局变量(即每个模板都可以访问的变量,比如网站标题、当前用户信息等),可以通过中间件的方式在上下文(ctx)上挂载变量,然后在渲染时将这些变量传递给模板引擎。
npm install koa-views ejs
const Koa = require('koa');
const views = require('koa-views');
const path = require('path');
const app = new Koa();
// 设置模板目录和引擎(这里以 ejs 为例)
app.use(views(path.join(__dirname, '/views'), {
extension: 'ejs'
}));
// 设置全局变量的中间件
app.use(async (ctx, next) => {
// 设置全局变量,所有模板都可以访问
ctx.state.siteName = '我的网站';
ctx.state.currentYear = new Date().getFullYear();
// 如果有用户登录信息,也可以挂载
// ctx.state.user = { name: '张三' };
await next();
});
// 示例路由
app.use(async (ctx) => {
if (ctx.path === '/') {
// 渲染模板时,除了可以传入局部变量,还可以使用 ctx.state 中的全局变量
await ctx.render('index', {
title: '首页',
// 这里的变量是局部的,和 ctx.state 的全局变量可以共存
});
}
});
app.listen(3000, () => {
console.log('Server is running on http://localhost:3000');
});
假设你的模板文件位于 /views/index.ejs:
<!DOCTYPE html>
<html>
<head>
<title><%= title %> - <%= siteName %></title>
</head>
<body>
<h1>欢迎来到 <%= title %></h1>
<p>网站名称:<%= siteName %></p>
<p>当前年份:<%= currentYear %></p>
</body>
</html>
✅ 注意:在 koa-views中,所有通过 ctx.state设置的变量,都会自动注入到每个渲染的模板中,你不需要手动传递它们!也就是说,你只需要在中间件里设置 ctx.state.xxx,然后在模板里直接用 <%= xxx %>就可以访问到。
如果你使用的是别的模板引擎,比如 koa-nunjucks-2,原理是一样的:
npm install koa-nunjucks-2
配置示例:
const Koa = require('koa');
const nunjucks = require('koa-nunjucks-2');
const path = require('path');
const app = new Koa();
// 配置 nunjucks 模板引擎
app.use(nunjucks({
ext: 'html',
path: path.join(__dirname, 'views'), // 模板目录
nunjucksConfig: {
trimBlocks: true,
},
}));
// 设置全局变量
app.use(async (ctx, next) => {
ctx.state.siteName = '我的网站';
await next();
});
app.use(async ctx => {
if (ctx.path === '/') {
await ctx.render('index', { title: '首页' });
}
});
app.listen(3000);
在 views/index.html模板中:
<h1>{{ title }}</h1>
<p>网站名称:{{ siteName }}</p>
✅ 推荐做法: 使用 ctx.state来设置全局变量,然后在模板中直接使用。
通过一个中间件来设置这些全局变量(如网站名、当前年份、菜单、用户信息等)。
大多数 Koa 的模板渲染中间件(如 koa-views, koa-nunjucks-2, koa-ejs等)都会自动将 ctx.state注入到模板上下文中,无需手动传递。
📌 常用全局变量可能包括: 网站名称(siteName)
当前年份(currentYear)
菜单数据(menus)
当前登录用户(user)
网站配置信息等
如果你真的想设置 Koa 应用级别的全局变量(不是请求级别的),你也可以挂载到 app.context上,例如:
app.context.siteName = '我的网站'; 但这种方式是应用级别的常量,所有请求共享同一个值,无法动态变化(比如不能根据用户不同显示不同内容)。所以推荐还是使用 ctx.state在中间件中设置。
如你使用的是其他模板引擎,欢迎告诉我,我可以给出对应示例!
在 Koa 中,app.context是 Koa 应用的应用级上下文对象,它是所有请求的 ctx(即 ctx的原型)的基对象。你可以在 app.context上定义一些全局共享的属性或方法,这些属性会被每个请求的 ctx自动继承。
但是!
❗ app.context上的属性默认情况下不会自动传递给模板引擎!
也就是说,即使你在 app.context上定义了变量,比如 app.context.siteName = '我的网站',在模板中不能直接使用 siteName,除非你手动将它传给模板渲染函数,或者通过中间件将其挂载到 ctx.state中。
app.context是 Koa 提供的一个对象,它是每个请求上下文 ctx的原型。你可以在它上面添加属性或方法,这样所有的 ctx都可以访问到它们,类似全局共享。
const Koa = require('koa');
const app = new Koa();
// 在 app.context 上定义全局属性
app.context.siteName = '我的网站';
app.context.currentYear = new Date().getFullYear();
app.use(async ctx => {
ctx.body = `
<h1>网站名称:${ctx.siteName}</h1>
<p>当前年份:${ctx.currentYear}</p>
`;
});
app.listen(3000);
✅ 在上面的普通 HTTP 响应中(ctx.body直接输出 HTML),你可以直接通过 ctx.siteName和 ctx.currentYear访问 app.context上的属性,因为 ctx是基于 app.context的。
如果你使用了模板引擎(如 koa-views, ejs, nunjucks等),并调用 ctx.render('index', { ... })来渲染页面,那么:
模板引擎只能访问你显式传递给模板的变量,以及某些中间件自动注入的变量(比如 ctx.state)。
app.context上的变量默认不会自动传给模板!
也就是说,你如果在 app.context上定义了:
app.context.siteName = '我的网站';
然后在模板中直接写:
<h1><%= siteName %></h1> <!-- 不会生效! -->
这是 无效的,因为模板引擎并不知道 siteName是从哪里来的,除非你手动传递它。
你可以在渲染时,手动将 app.context上的变量传进去:
app.use(async ctx => {
await ctx.render('index', {
title: '首页',
siteName: ctx.siteName, // 手动从 app.context (也就是 ctx) 中传递
currentYear: ctx.currentYear
});
});
模板中就可以用了:
<h1><%= title %></h1>
<p>网站名称:<%= siteName %></p>
<p>当前年份:<%= currentYear %></p>
由于大多数模板引擎(比如 koa-views)会自动将 ctx.state上的变量注入到模板中,你可以写一个中间件,在每个请求中将 app.context的某些属性复制到 ctx.state中:
// 中间件:将 app.context 的某些全局变量赋值到 ctx.state
app.use(async (ctx, next) => {
ctx.state.siteName = ctx.siteName; // 来自 app.context
ctx.state.currentYear = ctx.currentYear;
await next();
});
然后你就可以在模板中直接使用 ctx.state中的变量,而不用每次渲染都手动传:
<h1><%= title %></h1>
<p>网站名称:<%= siteName %></p> <!-- 来自 ctx.state -->
<p>当前年份:<%= currentYear %></p>
并且你的路由代码可以更干净:
app.use(async ctx => {
await ctx.render('index', {
title: '首页'
// 不需要再传 siteName 和 currentYear,因为它们已经在 ctx.state 中了
});
});
更常见的做法是:不直接使用 app.context存全局变量,而是使用中间件将全局变量统一设置到 ctx.state中,这样更灵活,也更容易维护。
比如:
// 全局中间件设置 ctx.state
app.use(async (ctx, next) => {
ctx.state.siteName = '我的网站'; // 直接定义,不依赖 app.context
ctx.state.currentYear = new Date().getFullYear();
await next();
});
这样你完全不用碰 app.context,而且在所有模板中都可以通过 <%= siteName %>直接访问(因为模板引擎自动注入 ctx.state)。
koa怎么设置全局变量
发布时间:2025-9-14
分类:技术
标签: koa 客户评价 node