program tip

jade 템플릿 파일에서 스크립트 파일로 변수를 전달하는 방법은 무엇입니까?

radiobox 2020. 7. 28. 08:23
반응형

jade 템플릿 파일에서 스크립트 파일로 변수를 전달하는 방법은 무엇입니까?


자바 스크립트 파일로 전달되지 않는 옥 템플릿 파일 (index.jade)에 선언 된 변수 (config)에 문제가있어서 자바 스크립트가 중단됩니다. 파일은 다음과 같습니다 (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')

다음은 내 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));

그리고 여기 내 자바 스크립트 파일의 일부가 충돌합니다 (public / javascripts / app.js).

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

localhost (내 자신의 컴퓨터)에서 개발 모드 (NODE_ENV = development)로 사이트를 실행하고 있습니다. 디버깅을 위해 node-inspector를 사용하고 있습니다.이 변수는 public / javascripts / app.js에서 구성 변수가 정의되어 있지 않다고 알려줍니다.

어떤 아이디어 ?? 감사!!


그것은이다 조금 늦었지만 ...

script.
  loginName="#{login}";

이것은 내 스크립트에서 잘 작동합니다. Express에서 나는 이것을하고있다 :

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

최신 옥이 다른 것 같아요?

머서.

edit: added "." after script to prevent Jade warning.


!{} is for unescaped code interpolation, which is more suitable for objects

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>

The idea is to prevent the attacker to:

  1. Break out of the variable: JSON.stringify escapes the quotes
  2. Break out of the script tag: if the variable contents (which you might not be able to control if comes from the database for ex.) has a </script> string, the replace statement will take care of it

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


#{} is for escaped string interpolation, which is suitable only if you're working with strings. It does not work with objects

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

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

In my case, I was attempting to pass an object into a template via an express route (akin to OPs setup). Then I wanted to pass that object into a function I was calling via a script tag in a pug template. Though lagginreflex's answer got me close, I ended up with the following:

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

This ensured the object was passed in as expected, rather than needing to deserialise in the function. Also, the other answers seemed to work fine with primitives, but when arrays etc. were passed along with the object they were parsed as string values.


If you're like me and you use this method of passing variables a lot, here's a write-less-code solution.

In your node.js route, pass the variables in an object called window, like this:

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

Then in your pug/jade layout file (just before the block content), you get them out like this:

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

As my layout.pug file gets loaded with each pug file, I don't need to 'import' my variables over and over.

This way all variables/objects passed to window 'magically' end up in the real window object of your browser where you can use them in Reactjs, Angular, ... or vanilla javascript.


See this question: JADE + EXPRESS: Iterating over object in inline JS code (client-side)?

I'm having the same problem. Jade does not pass local variables in (or do any templating at all) to javascript scripts, it simply passes the entire block in as literal text. If you use the local variables 'address' and 'port' in your Jade file above the script tag they should show up.

Possible solutions are listed in the question I linked to above, but you can either: - pass every line in as unescaped text (!= at the beginning of every line), and simply put "-" before every line of javascript that uses a local variable, or: - Pass variables in through a dom element and access through JQuery (ugly)

Is there no better way? It seems the creators of Jade do not want multiline javascript support, as shown by this thread in GitHub: https://github.com/visionmedia/jade/pull/405


Here's how I addressed this (using a MEAN derivative)

My variables:

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

First I had to make sure that the necessary config variables were being passed. MEAN uses the node nconf package, and by default is set up to limit which variables get passed from the environment. I had to remedy that:

config/config.js:

original:

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

after modifications:

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

Now I can set my variables like this:

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

Note: I reset the "heirarchy indicator" to "__" (double underscore) because its default was ":", which makes variables more difficult to set from bash. See another post on this thread.

Now the jade part: Next the values need to be rendered, so that javascript can pick them up on the client side. A straightforward way to write these values to the index file. Because this is a one-page app (angular), this page is always loaded first. I think ideally this should be a javascript include file (just to keep things clean), but this is good for a 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};

In my rendered html, this gives me a nice little script:

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

From this point it's easy for angular to utilize the code.

참고URL : https://stackoverflow.com/questions/8698534/how-to-pass-variable-from-jade-template-file-to-a-script-file

반응형