Как создать глобальные переменные, доступные во всех представлениях, используя Express/Node.JS?
Хорошо, поэтому я создал блог с помощью Jekyll и вы можете определить переменные в файле _config.yml
, которые доступны во всех шаблонах/макетах, В настоящее время я использую Node.JS/Express с EJS и ejs-locals (для частичных/макетов. Я ищу что-то похожее на глобальные переменные, такие как site.title
, которые находятся в _config.yml
, если кто-то знаком с Jekyll. У меня есть переменные, такие как название сайта (вместо названия страницы), имя автора/компании, которые остаются неизменными на всех моих страницах.
Вот пример того, что я делаю сейчас:
exports.index = function(req, res){
res.render('index', {
siteTitle: 'My Website Title',
pageTitle: 'The Root Splash Page',
author: 'Cory Gross',
description: 'My app description',
indexSpecificData: someData
});
};
exports.home = function (req, res) {
res.render('home', {
siteTitle: 'My Website Title',
pageTitle: 'The Home Page',
author: 'Cory Gross',
description: 'My app description',
homeSpecificData: someOtherData
});
};
Я хотел бы иметь возможность определять переменные, такие как название моего сайта, описание, автор и т.д. в одном месте, и иметь их доступными в моих макетах/шаблонах через EJS без необходимости передавать их в качестве параметров для каждого вызова res.render
, Есть ли способ сделать это и по-прежнему разрешать передавать другие переменные, специфичные для каждой страницы?
Ответы
Ответ 1
После того, как я смог изучить Справочник по API-интерфейсу Express 3, я обнаружил то, что искал. В частности, записи для app.locals
а затем немного дальше по res.locals
провели необходимые мне ответы.
Я сам обнаружил, что функция app.locals
принимает объект и сохраняет все свои свойства в виде глобальных переменных, привязанных к приложению. Эти глобальные переменные передаются как локальные переменные для каждого представления. Функция res.locals
, однако, привязана к запросу, и, таким образом, локальные переменные ответа доступны только для представлений, отображаемых во время этого конкретного запроса/ответа.
Так что для моего случая в моем приложении app.js
я добавил:
app.locals({
site: {
title: 'ExpressBootstrapEJS',
description: 'A boilerplate for a simple web application with a Node.JS and Express backend, with an EJS template with using Twitter Bootstrap.'
},
author: {
name: 'Cory Gross',
contact: '[email protected]'
}
});
Затем все эти переменные доступны в моих представлениях как site.title
, site.description
, author.name
, author.contact
.
Я мог бы также определять локальные переменные для каждого ответа на запрос с res.locals
или просто передавать переменные, такие как заголовок страницы, в качестве options
параметров в вызове render
.
EDIT: этот метод не позволит вам использовать эти локальные жители в вашем промежуточном программном обеспечении. Я на самом деле столкнулся с этим, как предлагает Pickels в комментарии ниже. В этом случае вам понадобится создать промежуточную функцию как таковую в его альтернативном (и оцененном) ответе. Функция промежуточного res.locals
должна будет добавить их в res.locals
для каждого ответа, а затем вызвать next
. Эта промежуточная функция должна быть размещена над любым другим промежуточным программным обеспечением, которое должно использовать эти локальные жители.
EDIT: Другое отличие между объявлением locals через app.locals
и res.locals
заключается в том, что с помощью app.locals
переменные устанавливаются один раз и сохраняются на протяжении всего срока действия приложения. Когда вы устанавливаете locals с res.locals
в вашем промежуточном программном обеспечении, они устанавливаются каждый раз, когда вы получаете запрос. В основном вы предпочитаете устанавливать глобальные переменные через app.locals
если значение не зависит от переменной req
запроса, переданной в промежуточное программное обеспечение. Если значение не изменится, то будет более эффективным для его установки только один раз в app.locals
.
Ответ 2
Вы можете сделать это, добавив их в объект locals в общем промежуточном программном обеспечении.
app.use(function (req, res, next) {
res.locals = {
siteTitle: "My Website Title",
pageTitle: "The Home Page",
author: "Cory Gross",
description: "My app description",
};
next();
});
Локали - это также функция, которая расширяет объект locals, а не перезаписывает его. Таким образом, следующее работает также
res.locals({
siteTitle: "My Website Title",
pageTitle: "The Home Page",
author: "Cory Gross",
description: "My app description",
});
Полный пример
var app = express();
var middleware = {
render: function (view) {
return function (req, res, next) {
res.render(view);
}
},
globalLocals: function (req, res, next) {
res.locals({
siteTitle: "My Website Title",
pageTitle: "The Root Splash Page",
author: "Cory Gross",
description: "My app description",
});
next();
},
index: function (req, res, next) {
res.locals({
indexSpecificData: someData
});
next();
}
};
app.use(middleware.globalLocals);
app.get('/', middleware.index, middleware.render('home'));
app.get('/products', middleware.products, middleware.render('products'));
Я также добавил общее промежуточное ПО рендеринга. Таким образом, вам не нужно добавлять res.render для каждого маршрута, что означает, что у вас есть лучшее повторное использование кода. Как только вы спуститесь на многоразовый путь промежуточного программного обеспечения, вы заметите, что у вас будет много строительных блоков, которые значительно ускорят развитие.
Ответ 3
Для Express 4.0 я обнаружил, что использование переменных уровня приложения работает несколько иначе, и ответ Кори не работает для меня.
Из документов: http://expressjs.com/en/api.html#app.locals
Я обнаружил, что вы можете объявить глобальную переменную для приложения в
app.locals
например
app.locals.baseUrl = "http://www.google.com"
И затем в вашем приложении вы можете получить доступ к этим переменным, а в вашем явном промежуточном программном обеспечении вы можете получить к ним доступ в объекте req как
req.app.locals.baseUrl
например.
console.log(req.app.locals.baseUrl)
//prints out http://www.google.com
Ответ 4
В вашем приложении app.js вам нужно добавить что-то вроде этого
global.myvar = 100;
Теперь, во всех ваших файлах, которые вы хотите использовать эту переменную, вы можете просто получить к ней доступ как myvar
Ответ 5
Один из способов сделать это, обновив переменную app.locals
для этого приложения в app.js
Установить через следующие
var app = express();
app.locals.appName = "DRC on FHIR";
Get/Access
app.listen(3000, function () {
console.log('[' + app.locals.appName + '] => app listening on port 3001!');
});
Разработайте скриншот из примера @RamRovi с небольшим улучшением.
![введите описание изображения здесь]()
Ответ 6
вы также можете использовать "глобальный"
Пример:
объявить следующее:
app.use(function(req,res,next){
global.site_url = req.headers.host; // hostname = 'localhost:8080'
next();
});
Используйте следующее: в любых представлениях или файле ejs <% console.log(site_url); % >
в js файлах console.log(site_url);
Ответ 7
Что я делаю для того, чтобы избежать загрязненной глобальной области действия, это создать script, который я могу включить где угодно.
// my-script.js
const ActionsOverTime = require('@bigteam/node-aot').ActionsOverTime;
const config = require('../../config/config').actionsOverTime;
let aotInstance;
(function () {
if (!aotInstance) {
console.log('Create new aot instance');
aotInstance = ActionsOverTime.createActionOverTimeEmitter(config);
}
})();
exports = aotInstance;
Выполнение этого будет создавать только один экземпляр и делиться им, где бы он ни находился. Я не уверен, связано ли это с тем, что переменная кэшируется или из-за внутреннего механизма ссылки для приложения (который может включать кэширование). Любые комментарии о том, как node разрешает это, было бы замечательно.
Возможно, также прочитайте это, чтобы понять суть работы:
http://fredkschott.com/post/2014/06/require-and-the-module-system/