Değişken jade şablon dosyasından bir betik dosyasına nasıl geçirilir?


119

Bir javascript dosyasına aktarılmayan bir jade şablon dosyasında (index.jade) bildirilen bir değişkenle (config) sorun yaşıyorum ve bu da benim javascript çökmesine neden oluyor. İşte dosya (views / index.jade):

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')

İşte app.js'min (sunucu tarafı) bir parçası:

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

Ve işte javascript dosyamın kilitlenen bir parçası (public / javascripts / app.js):

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

Siteyi localhost'ta (kendi makinem) geliştirme modunda (NODE_ENV = geliştirme) çalıştırıyorum. Hata ayıklama için node-inspector kullanıyorum, bu bana config değişkeninin public / javascripts / app.js'de tanımsız olduğunu söyledi.

Herhangi bir fikir?? Teşekkürler!!


Yanıtlar:


174

Bu bir var biraz geç ama ...

script.
  loginName="#{login}";

Bu benim senaryomda iyi çalışıyor. Express'te şunu yapıyorum:

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

Sanırım son yeşim farklı mı?

Merc.

düzenleme: eklendi "." Jade uyarısını önlemek için komut dosyasından sonra.


1
Cevabı kabul ettiğiniz için teşekkürler! Peki, kodunuzla ilgili asıl sorun neydi ?
Merc

Evet, şablondaki yerel değişkeni tırnak işaretleri ve # {} göstergesine sararak da bunu çalıştırdım.
Askdesigners

Bu cevap tehlikelidir, lagginreflex'in cevabı dizeyi doğru şekilde kodlar (giriş adındaki satırsonları kod yürütülmesine izin verebilir).
Paul Grove

Yani sorun, çift beklenirken sadece tek alıntılardı, değil mi?
Augustin Riedinger

Benim için sorun nokta oldu. Senaryo bloğunun sonunda vardı. "Komut dosyası" anahtar kelimesinden sonra gelen nokta ile bir cazibe gibi çalışır. Teşekkür ederim!
Mirko

103

!{}için tespit edilmeyen kodu için daha uygun olan, interpolasyon nesneleri

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>

Buradaki fikir, saldırganın şunları yapmasını önlemektir:

  1. Değişkenden JSON.stringifykopma : tırnak işaretlerinden kaçar
  2. Komut dosyası etiketinden ayrılın: Değişken içeriği (örneğin veritabanından gelip gelmediğini kontrol edemeyebilirsiniz) bir </script>dizeye sahipse , replace ifadesi bununla ilgilenir

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


#{}kaçan dize enterpolasyonu içindir , bu yalnızca dizelerle çalışıyorsanız uygundur. O çalışmıyor nesnelerle

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

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

1
Mükemmel cevap! Bu konuyu 20+ dakikadır araştırıyorum ve başka hiçbir cevap! {} İle # {} arasındaki farkı belirtmedi. Bunca zamandır düşündüm de! {], # {} Kelimesinin kullanımdan kaldırılan eşdeğeri idi ... Tekrar teşekkürler.
Patrick E.

Başa! Mükemmel cevap.
Scarysize

Harika cevap ve nesneler için işe yarıyor! Btw, JSONküresel bir nesne mi? Başka herhangi bir kütüphaneyi içe aktarmadan çalışıyor gibiydi. Eğer öyleyse, tarayıcı desteği ne olacak?
chharvey

@chharvey JSON , yerleşik bir javascript dilidir (Tarih veya Matematik gibi), tüm tarayıcılar bunu destekler.
laggingreflex

1
Bunun en iyi cevap olduğu konusunda hemfikirim, ancak buranın potansiyel olarak tehlikeli dizelerden kaçmak için doğru yer olduğunu düşünmüyorum. IMO replaceBu koddaki çağrıyı atlamak ve bu değere diğer herhangi bir girdi gibi davranmak daha iyi olacaktır . JSON.stringify'ın geçerli bir javascript üreteceği (veya başarısız olduğu) garantilidir ve bu potansiyel olarak tehlikeli değeri bellekte bulundurduktan sonra, kullanmadan önce gerektiği gibi temizlediğinizden emin olabilirsiniz.
Riley Lark

9

Benim durumumda, bir nesneyi bir ekspres yol aracılığıyla bir şablona geçirmeye çalışıyordum (OP'lerin kurulumuna benzer). Sonra bu nesneyi bir pug şablonundaki bir komut dosyası etiketi aracılığıyla çağırdığım bir işleve geçirmek istedim. Gerçi lagginreflex cevabı yakın beni, ben aşağıdaki ile sona erdi:

script.
    var data = JSON.parse('!{JSON.stringify(routeObj)}');
    funcName(data)

Bu, işlevde seriyi kaldırmaya ihtiyaç duymak yerine nesnenin beklendiği gibi aktarılmasını sağladı. Ayrıca, diğer cevaplar ilkellerle iyi çalışıyor gibi görünüyordu, ancak diziler vb. Nesne ile birlikte iletildiğinde, dizge değerleri olarak ayrıştırıldılar.


7

Eğer benim gibiyseniz ve bu değişkenleri geçirme yöntemini çok kullanıyorsanız, işte bir daha az kod yazma çözümü.

Node.js rotanızda, değişkenleri şu şekilde adlandırılan bir nesneye aktarın window:

router.get('/', function (req, res, next) {
    res.render('index', {
        window: {
            instance: instance
        }
    });
});

Daha sonra pug / jade layout dosyanızda (hemen öncesinde block content), onları şu şekilde çıkarırsınız :

if window
    each object, key in window
        script.
            window.!{key} = !{JSON.stringify(object)};

Layout.pug dosyam her bir pug dosyasıyla yüklendiğinde, değişkenlerimi defalarca 'içe aktarmam' gerekmiyor.

Bu şekilde, window'sihirli bir şekilde' aktarılan tüm değişkenler / nesneler window, tarayıcınızın Reactjs, Angular, ... veya vanilya javascript'te kullanabileceğiniz gerçek nesnesine ulaşır.


1
Bu gördüğüm en iyi cevap.
Tohir

3

İşte bunu nasıl ele aldım (bir MEAN türevi kullanarak)

Değişkenlerim:

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

İlk önce, gerekli yapılandırma değişkenlerinin geçirildiğinden emin olmalıydım. MEAN, düğüm nconf paketini kullanır ve varsayılan olarak ortamdan hangi değişkenlerin geçirileceğini sınırlamak için ayarlanır. Bunu düzeltmek zorundaydım:

config / config.js:

orijinal:

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

değişikliklerden sonra:

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

Şimdi değişkenlerimi şu şekilde ayarlayabilirim:

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

Not: "Heirarchy göstergesini" "__" (çift alt çizgi) olarak sıfırladım çünkü varsayılan değeri ":" idi, bu da değişkenlerin bash'den ayarlanmasını zorlaştırıyor. Bu konudaki başka bir gönderiye bakın.

Şimdi yeşim taşı kısmı: Daha sonra, javascript'in onları istemci tarafında alabilmesi için değerlerin oluşturulması gerekiyor. Bu değerleri dizin dosyasına yazmanın basit bir yolu. Bu tek sayfalık bir uygulama olduğu için (açısal), bu sayfa her zaman önce yüklenir. Bence ideal olarak bu bir javascript içerme dosyası olmalıdır (sadece işleri temiz tutmak için), ancak bu bir demo için iyidir.

Uygulamanın / kontrolörleri / 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
    }
  });
};

Uygulamanın / görünümler / 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};

Oluşturduğum html'de, bu bana güzel bir komut dosyası veriyor:

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

Bu noktadan itibaren, kodu kullanmak açısal için kolaydır.


Bu, kabul edilen yanıtın zaten söylediği şeyi söylemenin çok uzun soluklu bir yoludur. Dahası, MEAN, nconf vs.'den bahsetmek konu dışıdır. Soru, geliştirme yığınınızı nasıl yaptığınızla değil, değişkenleri istemciye nasıl aktaracağınızla ilgilidir. Yine de, bu cevap için hala çok çaba sarf ettiğiniz için, olumsuz oylama değil.
Mrchief

aşırı karmaşık
andygoestohollywood

2

Şu soruya bakın: JADE + EXPRESS: Satır içi JS kodunda (istemci tarafı) nesne üzerinde yineleme mi yapıyorsunuz?

Bendede aynı sorun var. Jade yerel değişkenleri javascript betiklerine aktarmaz (veya herhangi bir şablonlama yapmaz), tüm bloğu değişmez metin olarak geçirir. Jade dosyanızda betik etiketinin üzerinde yerel değişkenler 'adres' ve 'bağlantı noktası' kullanırsanız, bunlar görünmelidir.

Olası çözümler, yukarıda bağlantı verdiğim soruda listelenmiştir, ancak şunlardan birini yapabilirsiniz: - her satırı çıkış karaktersiz metin olarak iletebilir (! = Her satırın başında) ve basitçe "-" karakterini kullanan her javascript satırının önüne yerel değişken veya: - Değişkenleri bir dom öğesi aracılığıyla iletin ve JQuery aracılığıyla erişim (çirkin)

Daha iyi bir yol yok mu? Görünüşe göre Jade'in yaratıcıları, GitHub'da şu başlıkta gösterildiği gibi çok satırlı javascript desteği istemiyor: https://github.com/visionmedia/jade/pull/405

Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.