如题
// set static, dynamic helpers
_.extend(app.locals, {
config: config
});
express 可以通过这样的方式,然后在jade 中 调用 config 内的 属性。 Koa 中 我了解有一个state 。 但是 貌似同样的写法
// set static, dynamic helpers
_.extend(app.state, {
config: config
});
在jade 中也不能调用到
state
是context
的属性,应该是
_.extend(ctx.state, {config})
@hellopao 我在用的是 Koa2 ,不是 koa1 ,ctx 在使用中间件的时候 就没有了 ,用 this 来代替
没太明白你想要的效果。 你用jade,我就当做你在做的是一个MVC的项目,那么我们想在渲染的时候拿到数据,在koa1中可以这样:
yield this.render('see', {
users: users,
pager: {
totalCount: totalCount,
pageSize: pageSize,
pageNum: pageNum
}
配置好模板之后使用render,“see” 是将要被渲染的模板,后面的object对象,是你将要给这个模板传递的数据。koa2与koa1大体是一样的,在年初它还有很多坑的时候也捣鼓过,如果要在模板中得到你传递的数据,可参考
@wfsovereign web对象 有个生命周期的嘛 page ,request ,session , application ,每个阶段 都有可以调用包括它之上的变量, 就好似 在 page 中 可以 获取 request 的对象,session 的对象,application 的对象。在 request 中 可以 获取 session 的对象,application 的对象。
var express = require('express');
var session = require('express-session');
var app = express(); //这里 就是 创建了一个 application
//locals 可以在 其它层 获取 want_to_use_in_page
_.extend(app.locals, {
want_to_use_in_page: 'test'
});
这样写后 就可以在 jade 这个 page内 调用want_to_use_in_page ,而不用在 request 哪里去声明, 而且是任何一个 page内都可以。 而且在request 哪里也可以通过 res.locals.want_to_use_in_page 来 获取
span #{want_to_use_in_page} // 会输出 test
这样就可以用来 做 当前用户,权限等功能,在jade 内直接去判断,不用 每次都找出来吧。
现在的问题是 在使用koa的时候 有没有类似 express 的 locals这样的参数 可以 做 所有阶段的数据传递。 请问,我这样描述有清楚一点嘛?
@wfsovereign 在cnodeclub 这项目中的 middlewares/auth.js 就用这样的用法
ep.all('get_user', function (user) {
if (!user) {
return next();
}
user = res.locals.current_user = req.session.user = new UserModel(user);
if (config.admins.hasOwnProperty(user.loginname)) {
user.is_admin = true;
}
next();
});
app.js 中 也有
_.extend(app.locals, {
config: config
});
koa比较完整的 开源项目 我还没有找到,看到的那些 都没有涉及到 菜单的权限控制部分,所以不了解这么在jade 内去获取 session 层的东西
koa2给的例子里不就有ctx吗
// Koa application is now a class and requires the new operator.
const app = new Koa();
// uses async arrow functions
app.use(async (ctx, next) => {
try {
await next(); // next is now a function
} catch (err) {
ctx.body = { message: err.message };
ctx.status = err.status || 500;
}
});
app.use(async ctx => {
const user = await User.getById(ctx.session.userid); // await instead of yield
ctx.body = user; // ctx instead of this
});
express中其实app.locals能在ejs里面被找到的原因很简单,因为 app.render(name, options)方法里面 会进行如下的操作:
let renderoptions = {}
//将app.locals内容合并入renderoptions
merge(renderoptions, this.locals );
//将开发者调用的render方法传入的参数,合并入renderoptions
merge(renderoptions, options );
//...调用render方法
tryRender( view, renderoptions, done);
所以对于开发者来说,渲染页面的参数里其实被express自动加上了app.locals的内容,这也是为什么可以在模板里面直接调用app.locals中定义的方法或者变量的原因 我翻了下Koa2.x的源码,可以把你的属性挂载到ctx.state上实现一样的功能
当然明白了express的原理,我们在项目中也可以自己构造一个封装myRender中间件,来实现app.locals一样的功能,类似下面这样的:
funtion myRender(locals){
locals = locals || {};
return co.wrap(function * (ctx, next){
ctx.myRender = function * (view, options){
options = lodash.extend(locals, options);
yiled ctx.render(view, options);
}
yiled next()
})
}
一楼其实就给你正确的答案了
他说的ctx就是你认为的context,每个http请求都会根据中间件顺序动态生成一个context,这个ctx贯穿单个http请求在node服务器的整个生命周期 另外,koa1.x中的this,其实指向的就是这个ctx,只是在koa2.x中作为一个中间件参数显示传入了而已
@thomas0836 表述的很清楚了,你是想要有一个设置公共返回信息的地方,这里设置之后,每个view都能收到这个信息。
@hyj1991 童鞋已经给你方向了,十分详细,你可以参考参考。
此外,昨晚是看到你在微信群里问的,并且发了链接,所以你可以在那里找我的- -
@FoghostCn 我没有用 async ,只是用 Generator 函数
@wfsovereign 是吗?不知道 那个是你呢
@hyj1991 嗯嗯,其实我想了解的是,Koa 内 是否已经有 类似的接口可以直接用而已,不用自己又去做一个
koa本身并没有针对模板引擎做任何工作,在koa的源码里也仅仅只有初始化context.state = {};
的一行代码
如果不引入其他依赖的话可以自己写一个:
function myRender(dir, opts) {
return function* (next) {
this.render = (filename, locals) => {
this.body = jade.compileFile(path.join(dir, filename) + '.jade', opts)(locals);
};
yield next;
}
};
如果你用了co-render这样的模块的话可以这么写:
const render = require('co-render');
function myRender(dir, opts) {
opts = _extend({
engine: 'jade'
}, opts);
return function* (next) {
this.render = function* (filename, locals) {
this.body = yield render(path.join(dir, filename) + '.jade', _extend(opts, locals));
};
yield next;
}
};
我这是koa1的写法,你可以在opts上挂载全局的locals
对象
可以用中间件的形式使用app.use(myRender('path/to/views', locals))
@FoghostCn thx 我了解是什么问题了