Express.js Просмотр "globals"
Я использую Express.js(на Node.js), и я знаю, что вы можете визуализировать представление с помощью настраиваемых данных через параметр "locals". (res.render("template", { locals: { foo: "bar" } });
)
Есть ли способ иметь "глобалы"? (т.е. данные, доступные для каждого вида)
Я видел view options
, но это не рекурсивно, поэтому он заменяет локали, которые я устанавливаю, если я использую любые локали с моим шаблоном.
Это мой прецедент: я хочу сделать так, чтобы файлы CSS/JS можно добавлять на каждой странице, и это часть моего основного макета. Проблема в том, что если я не устанавливаю явно эти массивы на каждом рендере, я получаю ошибку undefined, поэтому в моем шаблоне мне всегда нужно танцевать typeof css !== "undefined"
. Кроме того, у меня есть другие варианты опций выбора, которые я не хочу явно добавлять в каждую из моих форм.
Ответы
Ответ 1
Стоит отметить тех, кто, возможно, столкнулся с этим вопросом после выпуска Express 3, что метод dynamicMelpers больше не существует.
Вместо этого вы можете использовать функцию app.locals, которая действует как объект, в котором вы можете хранить значения или функции, а затем делает их доступными для просмотра. Например: -
// In your app.js etc.
app.locals.title = "My App";
app.locals({
version: 3,
somefunction: function() {
return "function result";
}
});
// Then in your templates (shown here using a jade template)
=title
=version
=somefunction()
// Will output
My App
3
function result
Если вам нужен доступ к объекту запроса для извлечения информации, вы можете написать простую среднюю функцию и использовать переменную app.settings.
Например, если вы используете connect-flash для предоставления сообщений своим пользователям, вы можете сделать что-то вроде этого:
app.use(function(req, res, next) {
app.set('error', req.flash('error'));
next();
});
Что даст вам доступ к сообщению об ошибке с параметром = settings.error в вашем шаблоне.
Эти темы рассматриваются здесь, хотя и немного кратко: http://expressjs.com/api.html#app.locals
Обновление: Express 4
app.locals
теперь представляет собой простой объект JavaScript, поэтому каждое свойство должно быть установлено один за другим.
app.locals.version = 3;
app.locals.somefunction = function() {
return "function result";
}
res.locals
предоставляет точно такую же функциональность, за исключением того, что она должна использоваться для данных, специфичных для запроса, а не для данных приложения. Пользовательский объект или настройки являются обычным прецедентом.
res.locals.user = req.isAuthenticated() ? req.user : null;
res.locals.userSettings = {
backgroundColor: 'fff'
}
Ответ 2
Существует способ иметь "глобальные" переменные для представлений, используя динамические помощники вида.
Из руководства Express.js:
app.dynamicHelpers(OBJ)
Регистрирует помощники динамического вида. Помощники динамического просмотра просто функции, которые принимают req, res и оцениваются на сервере перед представлением представления. Возвращаемое значение этой функции становится локальной переменной связанный с.
app.dynamicHelpers({session: function (req, res) { return req.session; }});
У всех просмотров теперь будет сеанс доступный для того, чтобы данные сеанса могли быть доступ через session.name и т.д.:
Вы можете найти реальный пример того, как их использовать здесь: https://github.com/alessioalex/Nodetuts/tree/master/express_samples (node app.js для запуска приложения)
Ответ 3
Реальный пример использования опций просмотра, упомянутых автором:
var app = express.createServer();
app.configure(function() {
app.set('views', path.join(__dirname, '..', 'views'));
app.set('view engine', 'jade');
app.set('view options', {
assetVersion: 1
});
И затем в моем layout.jade(базовый шаблон для приложения в моем случае):
link(rel='stylesheet', href='/static/css/' + assetVersion + '/style.css')
script(src='/static/js/' + assetVersion + '/script.js')
С помощью этого небольшого трюка мне нужно только обновить переменную assetVersion
в одном месте, чтобы убедиться, что мои активы arent кэшированы в лаке или других местах.
Ответ 4
Я начал изучать исходный код, и я действительно обнаружил, что теперь это возможно в никогда не версиях Express. (пока доступно только через GitHub)
Ответ 5
Самый простой способ сделать это - создать переменную, представляющую набор локальных настроек по умолчанию для ваших просмотров. Затем создайте функцию, которая принимает объект, объединяет его с локалями и возвращает объединенный объект.
Я также передаю ВСЕ мои локали внутри объекта контейнера, т.е. {locals:{g:{prop:val}}}
, поэтому в моих представлениях я могу ссылаться на g.prop
, который просто вернет null
, когда он не будет установлен, вместо бросая ошибку undefined.
function default_page_vars(custom_vars){
var vars = {
footer: true,
host: req.headers.host.split(':')[0],
config: this.config
};
if(custom_vars){
for(var k in custom_vars){
vars[k] = custom_vars[k];
}
}
return {
g:vars
};
}
//within your handler
response.render(view, {
locals: default_page_vars(other_locals)
});
Ответ 6
Это скрытый ответ, но я, наконец, получил его на работу.
1) Это пример вокруг модуля connect-flash
2) Добавьте часть промежуточного программного обеспечения в server.js/app.js, чтобы добавить req
в locals
. Это позволяет шаблону вызывать request.flash()
всякий раз, когда это необходимо. Без этого flash()
будет потребляться при каждом запросе/перенаправлении, побеждая цель.
var app = module.exports = express()
, flash=require('connect-flash');
app.configure(function(){
...
app.use(express.session({ secret: "shhh" }));
// Start Router
app.use(flash());
app.use(function(req, res, next) {
res.locals.request = req;
next();
});
app.use(app.router);
});
3) Настройте свой маршрут как обычно (это coffeescript, но ничего особенного)
app.get '/home', (req, res) ->
req.flash "info", "this"
res.render "#{__dirname}/views/index"
4) Вызовите request.flash(), когда вы хотите получать сообщения. Они потребляются при каждом вызове, поэтому не используйте console.log или они исчезнут: -)
!!!
html
head
title= config.appTitle
include partials/_styles
body
include partials/_scripts
#header
a(href="/logout") Logout CURRENTUSER
h2= config.appTitle
#messages
- var flash = request.flash()
each flashType in ['info','warn','error']
if flash[flashType]
p.flash(class=flashType)
= flash[flashType]
block content
h1 content here