Zugriff auf lokale Express.js-Variablen in clientseitigem JavaScript

70

Neugierig, ob ich das richtig mache und wenn nicht, wie ihr das angehen würdet.

Ich habe eine Jade-Vorlage, die einige Daten rendern muss, die aus einer MongoDB-Datenbank abgerufen wurden, und ich muss auch Zugriff auf diese Daten in einer clientseitigen JavaScript-Datei haben.

Ich verwende Express.js und sende die Daten wie folgt an die Jade-Vorlage:

var myMongoDbObject = {name : 'stephen'};
res.render('home', { locals: { data : myMongoDbObject } });

Dann kann ich in home.jade Dinge tun wie:

p Hello #{data.name}!

Welches schreibt aus:

Hello stephen!

Jetzt möchte ich auch Zugriff auf dieses Datenobjekt in einer clientseitigen JS-Datei haben, damit ich das Objekt mit einem Klick bearbeiten kann, bevor ich es auf den Server zurückschicke, um die Datenbank zu aktualisieren.

Dies konnte ich erreichen, indem ich das "Daten" -Objekt in einem versteckten Eingabefeld in der Jade-Vorlage speicherte und dann den Wert dieses Felds in meiner clientseitigen JS-Datei abrief.

In home.jade

- local_data = JSON.stringify(data) // data coming in from Express.js
input(type='hidden', value=local_data)#myLocalDataObj

Dann kann ich in meiner clientseitigen JS-Datei wie folgt auf local_data zugreifen:

In myLocalFile.js

var localObj = JSON.parse($("#myLocalDataObj").val());
console.log(localObj.name);

Dieses Stringify / Parsing-Geschäft fühlt sich jedoch chaotisch an. Ich weiß, dass ich die Werte meines Datenobjekts an DOM-Objekte in meiner Jade-Vorlage binden und diese Werte dann mit jQuery abrufen kann, aber ich möchte Zugriff auf das tatsächliche Objekt haben, das von Express in meinem clientseitigen JS zurückkommt.

Ist meine Lösung optimal, wie würden Sie dies erreichen?

Braitsch
quelle
4
Ich habe vor ein paar Monaten tatsächlich ein npm-Paket erstellt, um genau dieses Problem zu lösen: github.com/brooklynDev/JShare
BFree

Antworten:

72

Wenn das Rendern abgeschlossen ist, wird nur das gerenderte HTML an den Client gesendet. Daher sind keine Variablen mehr verfügbar. Was Sie tun können, ist, anstatt das Objekt in das Eingabeelement zu schreiben, das Objekt als gerendertes JavaScript auszugeben:

script(type='text/javascript').
    var local_data =!{JSON.stringify(data)}

EDIT: Anscheinend benötigt Jade einen Punkt nach der ersten schließenden Klammer.

Amberlamps
quelle
Ich sehe immer noch "Daten" als undefiniert im Skript-Tag.
Braitsch
Ok, dies ist besser als meine Eingabefeldlösung, da es nicht erforderlich ist, die JSON-Zeichenfolge zurück in ein Objekt zu analysieren oder den Wert des Eingabefelds mit jQuery nachzuschlagen.
Braitsch
Das funktioniert bei mir nicht, ich bekomme [Objekt Objekt]. Könnte ich auf der Serverseite mit stringify oder parse etwas falsch machen?
Costa
4
@Costa Abhängig von Ihrer Ansichts-Engine können Sie JSON.stringify möglicherweise nicht in der Ansicht aufrufen. Stattdessen sollten Sie es in Ihrem Controller als Zeichenfolge festlegen und die Zeichenfolge als Variable wie {{{jsonData}}}(im Fall eines Lenkers) übergeben.
Tom
Die vorgeschlagene Lösung funktioniert. Ich empfehle außerdem Express-Expose, um eine sauberere und integrierte Methode zum Anzeigen von serverseitigen Variablen zu erhalten.
xmikex83
13

Ich mache es ein bisschen anders. In meinem Controller mache ich das:

res.render('search-directory', {
  title: 'My Title',
  place_urls: JSON.stringify(placeUrls),
});

Und dann verwende ich es im Javascript in meiner Jade-Datei folgendermaßen:

var placeUrls = !{place_urls};

In diesem Beispiel wird es für das Twitter Bootstrap Typeahead Plugin verwendet. Sie können dann so etwas verwenden, um es zu analysieren, wenn Sie Folgendes benötigen:

jQuery.parseJSON( placeUrls );

Beachten Sie auch, dass Sie die Einheimischen weglassen können: {}.

Jabbermonkey
quelle
+1 auf dem Zettel über das Auslassen der Einheimischen, ich wusste nicht, dass Sie das tun können.
Braitsch
1
Was bedeutet es , Einheimische auszulassen ? @ Braitsch
Mathakoot
@iamrudra Es ist nicht erforderlich, dem lokalen Objekt in der Renderfunktion das Wort "lokale" voranzustellen. res.render('home', { { data : myObject } })ist in Ordnung gegen, res.render('home', { locals : { data : myObject } })obwohl ich vorschlagen könnte, dass Sie es aus Gründen der Klarheit trotzdem tun.
Braitsch
@braitsch: das ist etwas neues für mich. Ich habe in der Schule Knoten- und Express-Projekte durchgeführt, aber noch nie das Objekt der Einheimischen verwendet. Könnten Sie mich bitte auf die richtigen Dokumente / Lesematerialien hinweisen?
Mathakoot
3

Verwenden von Jade-Vorlagen:

Wenn Sie ein @ Amberlamps-Codeausschnitt über einer enthaltenen statischen HTML-Datei einfügen, denken Sie daran, dies anzugeben !!! 5 oben, um zu vermeiden, dass Ihr Styling beschädigt wird , in views / index.jade :

!!! 5
script(type='text/javascript')
    var local_data =!{JSON.stringify(data)}

include ../www/index.html

Dies wird in Ihrer local_data-Variablen übergeben, bevor die eigentliche statische HTML-Seite geladen wird, sodass die Variable von Anfang an global verfügbar ist.

Serverside (mit Jade Templating Engine) - server.js :

app.set('views', __dirname + '/views');
app.set('view engine', 'jade');

app.get('/', ensureAuthenticated, function(request, response){
    response.render('index', { data: {currentUser: request.user.id} });
});

app.use(express.static(__dirname + '/www'));
AmpT
quelle
1

Sie müssen die lokalen Variablen beim Rendern nicht übergeben, lokale Variablen sind global. Geben Sie in Ihren Mops-Dateiaufruf keinen Schlüsselausdruck ein, z #{}. Verwenden Sie einfach etwas wie: base(href=base.url)

wo base.urlistapp.locals.base = { url:'/' };

Adrian Miranda
quelle
-1

Hast du schon von socket.io gehört? (http://socket.io/). Eine einfache Möglichkeit, über Express auf das Objekt zuzugreifen, besteht darin, einen Socket zwischen node.js und Ihrem Javascript zu öffnen. Auf diese Weise können Daten einfach an die Client-Seite übergeben und dann einfach mit Javascript bearbeitet werden. Der Code müsste nicht viel sein, einfach ein socket.emit()from node.js und ein socket.on()from the client. Ich denke, das wäre eine effektive Lösung!

Alex Roe
quelle
18
Dies ist mit einem Hammer, um eine Biene zu schlagen. Es fügt viele Anfragen für fast nichts hinzu.
Arnaud Rinquin
Genau, Socket.io ist in diesem Fall übertrieben. Ich suche nach der einfachsten Möglichkeit, JS-Variablen vom Server zu einem clientseitigen Skript zu transportieren.
Braitsch
3
LOL, ich mag irgendwie, was Alex vorschlägt, bam! ah all diese nervigen Einheimischen bam bam!
user1323136