Подтвердить что ты не робот

Express.js Просмотр "globals"

Я использую Express.js(на Node.js), и я знаю, что вы можете визуализировать представление с помощью настраиваемых данных через параметр "locals". (res.render("template", { locals: { foo: "bar" } });)

Есть ли способ иметь "глобалы"? (т.е. данные, доступные для каждого вида)

Я видел view options, но это не рекурсивно, поэтому он заменяет локали, которые я устанавливаю, если я использую любые локали с моим шаблоном.

Это мой прецедент: я хочу сделать так, чтобы файлы CSS/JS можно добавлять на каждой странице, и это часть моего основного макета. Проблема в том, что если я не устанавливаю явно эти массивы на каждом рендере, я получаю ошибку undefined, поэтому в моем шаблоне мне всегда нужно танцевать typeof css !== "undefined". Кроме того, у меня есть другие варианты опций выбора, которые я не хочу явно добавлять в каждую из моих форм.

4b9b3361

Ответ 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