2012-01-02 16 views
91

Mam problem ze zmienną (config) zadeklarowaną w pliku szablonu jade (index.jade), który nie jest przekazywany do pliku javascript, co powoduje awarię javascript. Tutaj jest plik (widoki/index.jade):Jak przekazać zmienną z pliku szablonu jade do pliku skryptu?

h1 #{title} 

script(src='./socket.io/socket.io.js') 
script(type='text/javascript') 
    var config = {}; 
    config.address = '#{address}'; 
    config.port = '#{port}'; 
script(src='./javascripts/app.js') 

tutaj jest częścią moich app.js (po stronie serwera):

app.use(express.bodyParser()); 
    app.use(express.methodOverride()); 
    app.use(app.router); 
    app.use(express.static(__dirname + '/public')); 
}); 

app.configure('development', function(){ 
    app.set('address', 'localhost'); 
    app.use(express.errorHandler({ dumpExceptions: true, showStack: true })); 
}); 

app.configure('production', function(){ 
    app.use(express.errorHandler()); 
}); 

// Routes 

app.get('/', function(req, res){ 
    res.render('index', { 
    address: app.settings.address, 
    port: app.settings.port 
}); 
}); 

if (!module.parent) { 
    app.listen(app.settings.port); 
    console.log("Server listening on port %d", 
app.settings.port); 
} 

// Start my Socket.io app and pass in the socket 
require('./socketapp').start(io.listen(app)); 

I tu jest częścią mojego javascript pliku awarii (public/javascripts/app.js):

(function() { 
     var socket = new io.Socket(config.address, {port: config.port, rememberTransport: false}); 

biegnę witrynę na tryb rozwoju (NODE_ENV = rozwój) na localhost (mój własny maszynowy). Używam inspektora węzłów do debugowania, który powiedział mi, że zmienna konfiguracyjna jest niezdefiniowana w public/javascripts/app.js.

Jakieś pomysły? Dzięki!!

+0

możliwy duplikat [zmiennych ExpressJS Pass do JavaScript] (http://stackoverflow.com/questions/9268951/expressjs-pass-variables-to-javascript) – laggingreflex

Odpowiedz

134

To trochę późno, ale ...

script. 
    loginName="#{login}"; 

to działa dobrze w moim skrypcie . W Express, robię to:

exports.index = function(req, res){ 
    res.render('index', { layout:false, login: req.session.login }); 
}; 

Chyba ostatni jade jest inny?

Merc.

edytuj: dodano "." po skrypcie, aby zapobiec ostrzeżeniu Jade.

+1

Dzięki za zaakceptowanie odpowiedzi! Jaki był więc problem z Twoim kodem? – Merc

+0

Tak, działa to również poprzez zawijanie zmiennej lokalnej w szablonie w cudzysłowie i wskaźnik # {}. – Askdesigners

+0

Ta odpowiedź jest niebezpieczna, odpowiedź lagginreflex poprawnie koduje ciąg znaków (nowe linie w nazwie użytkownika mogą umożliwić wykonanie kodu). –

2

Zobacz na to pytanie: JADE + EXPRESS: Iterating over object in inline JS code (client-side)?

Mam ten sam problem. Jade nie przekazuje zmiennych lokalnych (lub w ogóle nie wykonuje szablonów) do skryptów javascript, po prostu przekazuje cały blok jako tekst dosłowny. Jeśli użyjesz zmiennych lokalnych "adres" i "port" w swoim pliku Jade powyżej tagu skryptu, powinny się pokazać.

Możliwe rozwiązania są wymienione w pytaniu, do którego linkowałem powyżej, ale możesz: - przekazać każdą linię jako tekst bez zmiany znaczenia (! = Na początku każdej linii) i po prostu umieścić "-" przed każdą linią javascript używa zmiennej lokalnej lub: - Przekaż zmienne za pośrednictwem elementu dom i uzyskaj dostęp przez JQuery (brzydki)

Czy nie ma lepszego sposobu? Wydaje się, że twórcy nie chcą Jade multilinii javascript wsparcia, jak wynika z tego wątku na GitHub: https://github.com/visionmedia/jade/pull/405

78

!{} jest unescaped code interpolacji, który jest bardziej odpowiedni dla obiektów

script var data = !{JSON.stringify(data).replace(/<\//g, '<\\/')} 

{ foo: 'bar' } 
// becomes: 
<script>var data = {"foo":"bar"}</script> 

{ foo: 'bar</script><script>alert("xss")//' } 
// becomes: 
<script>var data = {"foo":"bar<\/script><script>alert(\"xss\")//"}</script> 

Chodzi o to, aby uniemożliwić atakującemu:

  1. wyrwać zmiennej: JSON.stringify ucieka cudzysłowy
  2. Przerwij tag script: if the variable co ntents (których możesz nie być w stanie kontrolować, jeśli pochodzi z bazy danych np.) Ma </script> ciąg, oświadczenie zastąpić zadba o niego

https://github.com/pugjs/pug/blob/355d3dae/examples/dynamicscript.pug


#{} jest uciekł string interpolation, który nadaje się tylko wtedy, gdy pracujemy z tekstem. To nie działa z obiektami

script var data = #{JSON.stringify(data)} 

//=> <script>var data = {&quot;foo&quot;:&quot;bar&quot;}</script> 
+1

Dziękuję bardzo! – Sgnl

+0

Doskonała odpowiedź! Przeszukałem ten temat przez ponad 20 minut i żadne inne odpowiedzi nie wskazywały na różnicę między! {} I # {}. Cały ten czas właśnie pomyślałem! {] Był przestarzałym odpowiednikiem # {} ... Jeszcze raz dziękuję. –

+0

Dziękuję bardzo! –

0

Oto jak ja skierowana ta (stosując pochodną myśli)

Moi zmienne:

{ 
    NODE_ENV : development, 
    ... 
    ui_varables { 
    var1: one, 
    var2: two 
    } 
} 

Najpierw miałem, aby upewnić się, że konieczne zmienne konfiguracyjne były przekazywane. MEAN używa pakietu nconf węzła i domyślnie jest ustawiony, aby ograniczyć, które zmienne są przekazywane ze środowiska. Musiałem zaradzić:

config/config.js:

oryginalny:

nconf.argv() 
    .env(['PORT', 'NODE_ENV', 'FORCE_DB_SYNC']) // Load only these environment variables 
    .defaults({ 
    store: { 
    NODE_ENV: 'development' 
    } 
}); 

po modyfikacjach:

nconf.argv() 
    .env('__') // Load ALL environment variables 
    // double-underscore replaces : as a way to denote hierarchy 
    .defaults({ 
    store: { 
    NODE_ENV: 'development' 
    } 
}); 

Teraz mogę ustawić moje zmienne tak:

export ui_varables__var1=first-value 
export ui_varables__var2=second-value 

Uwaga: Zresetowałem "wskaźnik heirarchy" do "__" (podwójny podkreślnik), ponieważ jego domyślny był ":", co sprawia, że ​​zmienne są trudniejsze do ustawienia z bash. Zobacz inny post w tym wątku.

Teraz część jade: Następnie wartości muszą być renderowane, aby javascript mógł je pobierać po stronie klienta. Prosty sposób zapisania tych wartości do pliku indeksu. Ponieważ jest to jednostronicowa aplikacja (kątowa), ta strona jest zawsze ładowana jako pierwsza. Myślę, że najlepiej byłoby, gdyby plik zawierał javascript (tylko po to, aby wszystko było w porządku), ale jest to dobre na demo.

app/controllers/index.js:

'use strict'; 
var config = require('../../config/config'); 

exports.render = function(req, res) { 
    res.render('index', { 
    user: req.user ? JSON.stringify(req.user) : "null", 
    //new lines follow: 
    config_defaults : { 
     ui_defaults: JSON.stringify(config.configwriter_ui).replace(/<\//g, '<\\/') //NOTE: the replace is xss prevention 
    } 
    }); 
}; 

app/views/index.jade:

extends layouts/default 

block content 
    section(ui-view) 
    script(type="text/javascript"). 
    window.user = !{user}; 
    //new line here 
    defaults = !{config_defaults.ui_defaults}; 

W moim renderowane html, to daje mi ładny mały skrypt :

<script type="text/javascript"> 
window.user = null;   
defaults = {"var1":"first-value","var2:"second-value"}; 
</script>   

Od w tym punkcie łatwo jest wykorzystać kod.

+0

Jest to bardzo długi sposób na powiedzenie, co już zostało powiedziane w zaakceptowanej odpowiedzi. Ponadto, wspomnienie o MEAN, nconf itp. Są nieistotne. Pytanie brzmi, jak przekazać zmienne do klienta, a nie w jaki sposób zrobiłeś swój stos dev. Nie tracąc jednak na wartości, ponieważ wciąż włożyłeś wiele wysiłku w tę odpowiedź. – Mrchief

+0

zbyt skomplikowane – andygoestohollywood

Powiązane problemy