जेड टेम्पलेट फ़ाइल से स्क्रिप्ट फ़ाइल में चर कैसे पास करें?


119

मुझे जेड टेम्पलेट फ़ाइल (index.jade) में घोषित एक चर (कॉन्फिग) से परेशानी हो रही है, जो एक जावास्क्रिप्ट फ़ाइल में पारित नहीं हुआ है, जो तब मेरी जावास्क्रिप्ट क्रैश करता है। यहाँ फ़ाइल (विचार / 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')

यहाँ मेरे app.js (सर्वर साइड) का एक हिस्सा है:

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

और यहाँ मेरी जावास्क्रिप्ट फ़ाइल का एक हिस्सा है जो क्रैश (सार्वजनिक / जावास्क्रिप्ट / app.js) करता है:

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

मैं लोकलहोस्ट (मेरी अपनी मशीन) पर विकास मोड (NODE_ENV = विकास) पर साइट चला रहा हूं। मैं डिबगिंग के लिए नोड-इंस्पेक्टर का उपयोग कर रहा हूं, जिसने मुझे बताया कि कॉन्फ़िगर चर सार्वजनिक / javascripts / app.js में अपरिभाषित है।

कोई विचार?? धन्यवाद!!


जवाबों:


174

यह एक है थोड़ा देर से लेकिन ...

script.
  loginName="#{login}";

यह मेरी स्क्रिप्ट में ठीक काम कर रहा है। एक्सप्रेस में, मैं यह कर रहा हूँ:

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

मुझे लगता है कि नवीनतम जेड अलग है?

मर्क।

संपादित करें: " जेड चेतावनी को रोकने के लिए स्क्रिप्ट के बाद।


1
उत्तर स्वीकार करने के लिए धन्यवाद! तो, आपके कोड के साथ वास्तविक समस्या क्या थी ?
बुध

हां, मुझे यह काम स्थानीय टेम्पलेट में कोटेशन और # {} इंडिकेटर में लपेटकर भी मिला।
20

यह उत्तर खतरनाक है, लैगिनएर्गेलेक्स का उत्तर स्ट्रिंग को सही ढंग से एन्कोड करता है (लॉगिन नाम में नई रूपरेखा कोड निष्पादन की अनुमति दे सकती है)।
पॉल ग्रोव

तो मुद्दा केवल सिंगल कोट्स का था जबकि डबल की उम्मीद है, है ना?
अगस्टिन रिडिंगर

मेरे लिए मुद्दा डॉट था। मेरे पास स्क्रिप्ट ब्लॉक के अंत में था। "स्क्रिप्ट" कीवर्ड के बाद डॉट के साथ यह एक आकर्षण की तरह काम करता है। धन्यवाद!
मिरको

102

!{}बिना कोड के प्रक्षेप के लिए है, जो वस्तुओं के लिए अधिक उपयुक्त है

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>

विचार हमलावर को रोकने के लिए है:

  1. चर से बाहर तोड़ो: JSON.stringifyउद्धरण से बच जाता है
  2. स्क्रिप्ट टैग से बाहर निकलना: यदि चर सामग्री (जो आप डेटाबेस से बाहर आने के लिए नियंत्रित करने में सक्षम नहीं हो सकती है।) में एक </script>स्ट्रिंग है, तो प्रतिस्थापित विवरण इसका ध्यान रखेगा।

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


#{}फरार स्ट्रिंग प्रक्षेप के लिए है , जो तभी उपयुक्त है जब आप तार के साथ काम कर रहे हों। यह वस्तुओं के साथ काम नहीं करता है

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

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

1
बहुत बढ़िया जवाब! मैं इस विषय पर 20+ मिनट से खोज कर रहा हूं और किसी अन्य उत्तर में अंतर नहीं बताया गया है! {} और # {}। इस पूरे समय मैं सिर्फ सोचा था! {] # {} ... के बराबर पदावनत था ... फिर से धन्यवाद।
पैट्रिक ई।

सबसे ऊपर! बहुत बढ़िया जवाब।
13

महान जवाब, और यह वस्तुओं के लिए काम करता है! Btw, JSONएक वैश्विक वस्तु है? यह किसी भी अन्य पुस्तकालयों के आयात के बिना काम करने के लिए लग रहा था। यदि हां, तो ब्राउज़र समर्थन के बारे में क्या?
छुरी

@chharvey JSON एक जावास्क्रिप्ट भाषा बिल्टिन (जैसे दिनांक या गणित) है, सभी ब्राउज़र इसका समर्थन करते हैं।
लैगिंगफ्लेक्स

1
सहमत यह सबसे अच्छा जवाब है, लेकिन मुझे नहीं लगता कि संभावित खतरनाक तारों से बचने के लिए यह सही जगह है। IMO replaceइस कोड में कॉल को छोड़ना बेहतर होगा , और किसी अन्य इनपुट की तरह ही इस मान का इलाज करें। JSON.stringify को वैध जावास्क्रिप्ट (या विफल) का उत्पादन करने की गारंटी दी जाती है, और आपके पास स्मृति में इस संभावित-खतरनाक मूल्य के बाद आप उपयोग से पहले आवश्यकतानुसार इसे साफ कर सकते हैं।
रिले लार्क

9

मेरे मामले में, मैं एक ऑब्जेक्ट को एक्सप्रेस मार्ग (ओपीएस सेटअप के समान) के माध्यम से एक टेम्पलेट में पारित करने का प्रयास कर रहा था। तब मैं उस ऑब्जेक्ट को एक फंक्शन में पास करना चाहता था जिसे मैं एक पग टेम्पलेट में स्क्रिप्ट टैग के माध्यम से बुला रहा था। हालांकि लैगिनेफ्लेक्स का जवाब मुझे करीब मिला, मैंने निम्नलिखित के साथ समाप्त किया:

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

यह सुनिश्चित करता है कि वस्तु को अपेक्षित रूप से पारित किया गया था, बजाय इसके कि फ़ंक्शन में deserialise की आवश्यकता थी। इसके अलावा, अन्य उत्तर आदिम के साथ ठीक काम करने के लिए लग रहे थे, लेकिन जब सरणियों आदि को ऑब्जेक्ट के साथ पारित किया गया तो उन्हें स्ट्रिंग मान के रूप में पार्स किया गया।


7

यदि आप मेरे जैसे हैं और आप चर को पार करने के इस तरीके का उपयोग करते हैं, तो यहां एक लिखित-कम-कोड समाधान है।

अपने नोड.जेएस मार्ग में, चर को किसी ऑब्जेक्ट में पास करें window, जैसे कि:

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

फिर अपने पग / जेड लेआउट फ़ाइल में (बस पहले block content), आप उन्हें इस तरह से बाहर निकालते हैं:

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

जैसे ही मेरा लेआउट.पग फ़ाइल प्रत्येक पग फ़ाइल से लोड हो जाता है, मुझे अपने चर को 'आयात' करने की आवश्यकता नहीं होती है।

इस तरह से आपके ब्राउज़र windowके वास्तविक windowऑब्जेक्ट में 'जादुई' अंत तक चले गए सभी वेरिएबल्स / ऑब्जेक्ट्स जहाँ आप उन्हें Reactjs, Angular, ... या वेनिला जावास्क्रिप्ट में उपयोग कर सकते हैं।


1
यह सबसे अच्छा जवाब है जो मैंने देखा है।
तोहरी

3

यहां बताया गया है कि मैंने इसे कैसे संबोधित किया (MEAN व्युत्पन्न का उपयोग करके)

मेरे चर:

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

पहले मुझे यह सुनिश्चित करना था कि आवश्यक कॉन्फ़िगरेशन चर पास किए जा रहे थे। MEAN नोड nconf पैकेज का उपयोग करता है, और डिफ़ॉल्ट रूप से यह सीमित करने के लिए सेट किया जाता है कि कौन से चर पर्यावरण से पारित हो जाते हैं। मुझे यह उपाय करना था:

config / config.js:

मूल:

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

संशोधनों के बाद:

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

अब मैं इस तरह अपने चर सेट कर सकते हैं:

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

नोट: मैं "हेइरार्की इंडिकेटर" को "__" (डबल अंडरस्कोर) पर रीसेट करता हूं क्योंकि इसका डिफॉल्ट ":" था, जो वैरिएबल को बैश से सेट करना अधिक कठिन बनाता है। इस धागे पर एक और पोस्ट देखें।

अब जेड भाग: अगले मूल्यों को प्रदान करने की आवश्यकता है, ताकि जावास्क्रिप्ट उन्हें क्लाइंट की तरफ ले जा सके। इन मूल्यों को इंडेक्स फ़ाइल में लिखने का एक सीधा तरीका। क्योंकि यह एक-पृष्ठ ऐप (कोणीय) है, यह पृष्ठ हमेशा पहले लोड किया जाता है। मुझे लगता है कि आदर्श रूप से यह एक जावास्क्रिप्ट होनी चाहिए जिसमें फ़ाइल शामिल है (बस चीजों को साफ रखने के लिए), लेकिन यह एक डेमो के लिए अच्छा है।

एप्लिकेशन / नियंत्रक / 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
    }
  });
};

एप्लिकेशन / विचारों / 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};

मेरे रेंडर किए गए HTML में, यह मुझे एक छोटी सी स्क्रिप्ट देता है:

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

इस बिंदु से कोणीय के लिए कोड का उपयोग करना आसान है।


यह कहने का एक बहुत लंबा घुमावदार तरीका है कि पहले से ही स्वीकृत उत्तर क्या कहता है। इसके अलावा, MEAN, nconf आदि का उल्लेख करना अप्रासंगिक है। सवाल यह है कि क्लाइंट को वैरिएबल कैसे पास किया जाए, इस बारे में नहीं कि आपने अपना देव स्टैक कैसे किया। हालांकि, आप इस उत्तर में बहुत प्रयास करने के बाद भी नीच नहीं हैं।
मचिफ नोव

अत्यधिक जटिल
andygoestohollywood

2

इस प्रश्न को देखें: JADE + EXPRESS: इनलाइन JS कोड (क्लाइंट-साइड) में ऑब्जेक्ट पर फेरबदल?

मुझे भी यही तकलीफ़ है। जेड स्क्रिप्ट स्क्रिप्ट्स के लिए (या किसी भी तरह की कोई भी टेम्प्लेटिंग) स्थानीय वेरिएबल्स को पास नहीं करता है, यह बस पूरे ब्लॉक को शाब्दिक पाठ के रूप में पास करता है। यदि आप स्क्रिप्ट टैग के ऊपर अपनी जेड फ़ाइल में स्थानीय चर 'पता' और 'पोर्ट' का उपयोग करते हैं तो उन्हें दिखाना चाहिए।

संभावित समाधान उस प्रश्न में सूचीबद्ध हैं जो मैं ऊपर दिए गए लिंक से जुड़ा हुआ हूं, लेकिन आप या तो कर सकते हैं: - हर पंक्ति को अनुत्तरित पाठ ((हर पंक्ति की शुरुआत में!) के रूप में पास करें), और बस जावास्क्रिप्ट का उपयोग करने वाली जावास्क्रिप्ट की प्रत्येक पंक्ति से पहले "-" डालें! स्थानीय चर, या: - एक चर तत्व के माध्यम से चर और JQuery के माध्यम से पहुँच (बदसूरत)

क्या कोई बेहतर तरीका नहीं है? ऐसा लगता है कि जेड के निर्माता मल्टीलाइन जावास्क्रिप्ट का समर्थन नहीं चाहते हैं, जैसा कि गीथहब में इस धागे द्वारा दिखाया गया है: https://github.com/visionmedia/jade/pull/405

हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.