Jak utworzyć zmienne globalne dostępne we wszystkich widokach za pomocą Express / Node.JS?

Ok, więc zbudowałem bloga używającJekyll i możesz zdefiniować zmienne w pliku _config.yml, które są dostępne we wszystkich szablonach/układach. Obecnie używam Node.JS / Express z szablonami EJS i ejs-locals (dla częściowych / układów. Szukam czegoś podobnego do zmiennych globalnych, takich jak site.title, które znajdują się w _config.yml, jeśli ktoś jest zaznajomiony z Jekyllem. Mam zmienne takie jak tytuł strony, (zamiast tytuł strony), Autor/Nazwa firmy, które pozostają takie same na wszystkich moich stronach.

Oto przykład tego, co obecnie robię.:

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
    });
};

Chciałbym móc definiować zmienne takie jak tytuł, opis, autor itp. w jednym miejscu i mieć je dostępne w moich układach/szablonach za pośrednictwem EJS bez konieczności przekazywania ich jako opcji do każdego wywołania do res.render. Czy istnieje sposób, aby to zrobić i nadal pozwalają mi przekazać inne zmienne specyficzne dla każdej strony?

Author: Brad Larson, 2013-05-08

8 answers

Po tym, jak miał okazję studiować Express 3 API Reference trochę więcej odkryłem to, czego szukałem. W szczególności wpisy dla app.locals a potem trochę dalej w dół res.locals trzymałem odpowiedzi, których potrzebowałem.

Odkryłem dla siebie, że funkcja app.locals przyjmuje obiekt i przechowuje wszystkie jego właściwości jako zmienne globalne o zasięgu do aplikacji. Globale te są przekazywane jako zmienne lokalne do każdego widoku. Funkcja res.locals jest jednak ograniczona do żądania i dlatego zmienne lokalne response są dostępne tylko dla widoków renderowanych podczas danego żądania / odpowiedzi.

Więc dla mojego przypadku w moim app.js dodałem:

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]'
    }
});

Wtedy wszystkie te zmienne są dostępne w moich poglądach jako site.title, site.description, author.name, author.contact.

Mogę również zdefiniować zmienne lokalne dla każdej odpowiedzi na żądanie za pomocą res.locals, lub po prostu przekazać zmienne takie jak tytuł strony jako options parametr w wywołaniu render.

EDIT: ta metoda pozwoli , a nie na użycie tych miejscowych w oprogramowaniu pośredniczącym. Rzeczywiście natknąłem się na to, jak sugeruje Pickels w komentarzu poniżej. W takim przypadku będziesz musiał stworzyć funkcję middleware jako taką w swojej alternatywnej (i docenianej) odpowiedzi. Funkcja middleware będzie musiała dodać je do res.locals dla każdej odpowiedzi, a następnie wywołać next. Ta funkcja middleware będzie musiała być umieszczona ponad innymi / align = "left" /

EDIT: inną różnicą między deklarowaniem lokalnych przez app.locals i res.locals jest to, że z app.locals zmienne są ustawiane jednorazowo i utrzymują się przez cały okres użytkowania aplikacji. Gdy ustawisz lokalne z res.locals w oprogramowaniu pośredniczącym, są one ustawiane za każdym razem, gdy otrzymujesz żądanie. Zasadniczo powinieneś preferować ustawianie globali za pomocą app.locals, chyba że wartość zależy od zmiennej request req przekazanej do oprogramowania pośredniczącego. Jeśli wartość nie Zmień wtedy będzie bardziej wydajne, aby było ustawione tylko raz w app.locals.

 110
Author: Cory Gross,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2018-11-30 18:03:31

Możesz to zrobić, dodając je do obiektu locals w ogólnym oprogramowaniu pośredniczącym.

app.use(function (req, res, next) {
   res.locals = {
     siteTitle: "My Website's Title",
     pageTitle: "The Home Page",
     author: "Cory Gross",
     description: "My app's description",
   };
   next();
});

Locals jest również funkcją, która rozszerza obiekt locals zamiast go nadpisywać. Tak więc następujące działania również

res.locals({
  siteTitle: "My Website's Title",
  pageTitle: "The Home Page",
  author: "Cory Gross",
  description: "My app's description",
});

Pełny przykład

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's Title",
            pageTitle: "The Root Splash Page",
            author: "Cory Gross",
            description: "My app's 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'));

Dodałem również ogólne render middleware. W ten sposób nie musisz dodawać res.render do każdej trasy, co oznacza, że masz lepsze ponowne użycie kodu. Po zejściu na ścieżkę oprogramowania pośredniego wielokrotnego użytku zauważysz, że będziesz mieć wiele klocków, które ogromnie przyspieszą rozwój.

 57
Author: Pickels,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2015-11-05 03:49:24

Dla Express 4.0 stwierdziłem, że używanie zmiennych poziomu aplikacji działa trochę inaczej i odpowiedź Cory ' ego nie zadziałała dla mnie.

From the docs: http://expressjs.com/en/api.html#app.locals

Znalazłem, że Można zadeklarować zmienną globalną dla aplikacji w

app.locals

E. g

app.locals.baseUrl = "http://www.google.com"

A następnie w aplikacji możesz uzyskać dostęp do tych zmiennych i w oprogramowaniu pośredniczącym express możesz uzyskać do nich dostęp w obiekcie req jako

req.app.locals.baseUrl

Np.

console.log(req.app.locals.baseUrl)
//prints out http://www.google.com
 18
Author: RamRovi,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2016-03-18 05:08:17

W Twojej aplikacji.js musisz dodać coś takiego

global.myvar = 100;

Teraz, we wszystkich plikach, które chcesz użyć tej zmiennej, możesz po prostu uzyskać do niej dostęp jako myvar

 14
Author: Fernando Bustos,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2016-07-21 17:57:49

Można to zrobić poprzez aktualizację zmiennej app.locals dla tej aplikacji w app.js

Set via following

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!');
});

Opracowanie zrzutu ekranu z przykładu @ RamRovi z lekkim ulepszeniem.

Tutaj wpisz opis obrazka

 1
Author: Gajen Sunthara,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2016-07-21 17:59:09

Możesz również użyć "global"

Przykład:

Declare like this:

  app.use(function(req,res,next){
      global.site_url = req.headers.host;   // hostname = 'localhost:8080'
      next();
   });

Użyj w ten sposób: w dowolnych widokach lub pliku ejs

W plikach js konsola.log (site_url);

 1
Author: Shaik Matheen,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2016-10-21 08:02:48

Z odpowiedziami differents, zaimplementowałem ten kod, aby użyć zewnętrznego pliku JSON załadowanego w "aplikacji.miejscowi "

Parametry

{
    "web": {
        "title" : "Le titre de ma Page",
        "cssFile" : "20200608_1018.css"
    }
}

Zastosowanie

var express     = require('express');
var appli       = express();
var serveur     = require('http').Server(appli);

var myParams    = require('./include/my_params.json');
var myFonctions = require('./include/my_fonctions.js');

appli.locals = myParams;

Strona EJS

<!DOCTYPE html>
<html lang="fr">
<head>
    <meta charset="UTF-8">
    <title><%= web.title %></title>
    <link rel="stylesheet" type="text/css" href="/css/<%= web.cssFile %>">
</head>

</body>
</html>

Nadzieję, że to pomoże

 0
Author: Juan - 6510866,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2020-06-10 09:24:15

To, co robię, aby uniknąć zanieczyszczonego globalnego zasięgu, to tworzenie skryptu, który mogę umieścić w dowolnym miejscu.

// 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;

Spowoduje to utworzenie nowej instancji tylko raz i udostępnienie jej wszędzie tam, gdzie plik jest dołączony. Nie jestem pewien, czy to dlatego, że zmienna jest buforowana, czy z powodu wewnętrznego mechanizmu odniesienia dla aplikacji (który może zawierać buforowanie). Wszelkie uwagi na temat tego, jak node rozwiązuje to byłoby świetne.

Może również przeczytać to, aby uzyskać gist na jak działa require: http://fredkschott.com/post/2014/06/require-and-the-module-system/

 -1
Author: dewwwald,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2017-07-26 11:46:29