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

javascript 파일로 전달되지 않은 jade 템플릿 파일 (index.jade)에 선언 된 변수 (config)에 문제가 있습니다. 이로 인해 javascript 충돌이 발생합니다. 다음은 파일 (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를 사용하고 있는데, config 변수가 public / javascripts / app.js에 정의되어 있지 않다고 말했습니다.

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



답변

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

script.
  loginName="#{login}";

이것은 내 스크립트에서 잘 작동합니다. Express에서는 다음을 수행합니다.

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

최신 비취가 다른 것 같아요?

Merc.

편집 : “.”추가 Jade 경고를 방지하기 위해 스크립트 후.


답변

!{}위한 이스케이프 코드 에 더 적합하다 보간 개체

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>문자열이 있으면 replace 문이 처리합니다.

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>


답변

제 경우에는 익스프레스 경로 (OPs 설정과 유사)를 통해 개체를 템플릿에 전달하려고했습니다. 그런 다음 퍼그 템플릿의 스크립트 태그를 통해 호출 한 함수에 해당 개체를 전달하고 싶었습니다. lagginreflex의 답변 이 나를 가까워 졌지만 결국 다음과 같이 끝났습니다.

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

이렇게하면 함수에서 역 직렬화 할 필요없이 개체가 예상대로 전달됩니다. 또한 다른 답변은 기본 요소에서 잘 작동하는 것처럼 보였지만 배열 등이 객체와 함께 전달되면 문자열 값으로 구문 분석되었습니다.


답변

나처럼 변수를 많이 전달하는이 방법을 사용하는 경우 쓰기없는 코드 솔루션이 있습니다.

node.js 경로에서 window다음과 같이 라는 객체에 변수를 전달합니다 .

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

그런 다음 pug / jade 레이아웃 파일 (바로 앞 block content)에서 다음과 같이 가져옵니다.

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

내 layout.pug 파일이 각 pug 파일과 함께로드되므로 내 변수를 반복해서 ‘가져올’필요가 없습니다.

이렇게하면 window‘마법처럼’ 전달 된 모든 변수 / 객체가 window브라우저 의 실제 객체에 들어가서 Reactjs, Angular, … 또는 바닐라 자바 ​​스크립트에서 사용할 수 있습니다.


답변

이 문제를 해결 한 방법은 다음과 같습니다 (평균 파생 상품 사용).

내 변수 :

{
  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

참고 : 기본값이 “:”이기 때문에 “heirarchy indicator”를 “__”(이중 밑줄)로 재설정하여 bash에서 변수를 설정하기가 더 어렵습니다. 이 스레드에 대한 다른 게시물을 참조하십시오.

이제 jade 부분 : 다음으로 값을 렌더링해야 javascript가 클라이언트 측에서 선택할 수 있습니다. 이러한 값을 색인 파일에 쓰는 간단한 방법입니다. 한 페이지 앱 (각도)이므로이 페이지는 항상 먼저로드됩니다. 이상적으로는 이것이 자바 스크립트 포함 파일이어야한다고 생각하지만 (일단을 깨끗하게 유지하기 위해) 이것은 데모에 좋습니다.

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

내 렌더링 된 html에서 이것은 나에게 멋진 작은 스크립트를 제공합니다.

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

이 시점에서 앵귤러는 코드를 쉽게 활용할 수 있습니다.


답변

이 질문을보십시오 : JADE + EXPRESS : 인라인 JS 코드 (클라이언트 측)에서 객체를 반복합니까?

나는 같은 문제가 있습니다. Jade는 지역 변수를 자바 스크립트 스크립트에 전달하지 않습니다 (또는 템플릿을 전혀 수행하지 않음). 단순히 전체 블록을 리터럴 텍스트로 전달합니다. Jade 파일에서 스크립트 태그 위의 지역 변수 ‘address’와 ‘port’를 사용하면 표시되어야합니다.

가능한 해결책은 위에서 링크 한 질문에 나열되어 있지만 다음 중 하나를 수행 할 수 있습니다.-모든 줄을 이스케이프 처리되지 않은 텍스트 (모든 줄의 시작 부분에! =)로 전달하고 javascript의 모든 줄 앞에 “-“를 입력합니다. 지역 변수 또는 :-dom 요소를 통해 변수를 전달하고 JQuery를 통해 액세스합니다.

더 좋은 방법이 없습니까? GitHub : https://github.com/visionmedia/jade/pull/405의 스레드에서 볼 수 있듯이 Jade 제작자는 여러 줄 자바 스크립트 지원을 원하지 않는 것 같습니다.


답변