如何将变量从玉模板文件传递到脚本文件?

时间:2012-01-02 07:46:29

标签: javascript node.js pug

我遇到了在jade模板文件(index.jade)中声明的变量(config)的问题,该文件未传递给javascript文件,然后使我的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));

这是我的javascript文件的一部分崩溃(public / javascripts / app.js):

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

我在localhost(我自己的机器)上以开发模式(NODE_ENV =开发)运行该站点。我正在使用node-inspector进行调试,它告诉我在public / javascripts / app.js中未定义config变量。

任何想法?谢谢!

5 个答案:

答案 0 :(得分:154)

这是迟到但是......

script.
  loginName="#{login}";

这在我的脚本中工作正常。在Express中,我这样做:

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

我猜最新的玉石有什么不同?

Merc的。

编辑:添加“。”在脚本之后防止Jade警告。

答案 1 :(得分:92)

!{} 用于unescaped code插值,更适合对象

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>字符串,则替换语句将处理它< / LI>

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


    #{} 适用于转发string interpolation,仅在您使用字符串时才适用。 无效与对象

    script var data = #{JSON.stringify(data)}
    
    //=> <script>var data = {&quot;foo&quot;:&quot;bar&quot;}</script>
    

答案 2 :(得分:4)

如果您像我一样,并且经常使用这种传递变量的方法,那么这是一种无需编写代码的解决方案。

在您的node.js路由中,将变量传递到名为Limit的对象中,如下所示:

window

然后在哈巴狗/玉器布局文件中(就在router.get('/', function (req, res, next) { res.render('index', { window: { instance: instance } }); }); 之前),将它们按以下方式取出:

block content

随着我的layout.pug文件与每个pug文件一起加载,我不需要一遍又一遍地“导入”变量。

通过这种方式,“神奇地”传递给if window each object, key in window script. window.!{key} = !{JSON.stringify(object)}; 的所有变量/对象最终都出现在浏览器的真实window对象中,您可以在Reactjs,Angular,...或vanilla javascript中使用它们。

答案 3 :(得分:2)

请参阅此问题:JADE + EXPRESS: Iterating over object in inline JS code (client-side)?

我遇到了同样的问题。 Jade不会将局部变量传递给javascript脚本(或根本不做任何模板),它只是将整个块作为文字文本传递。如果您在脚本标记上方的Jade文件中使用局部变量'address'和'port',则应显示它们。

我在上面链接的问题中列出了可能的解决方案,但您可以:    - 将每行作为未转义的文本传递(!=在每行的开头),并在每行使用局部变量的javascript之前简单地加上“ - ”,或者:    - 通过dom元素传递变量并通过JQuery(丑陋)访问

有没有更好的方法?似乎Jade的创建者不需要多行javascript支持,如GitHub中的这个帖子所示:https://github.com/visionmedia/jade/pull/405

答案 4 :(得分:1)

以下是我如何解决这个问题(使用MEAN派生词)

我的变数:

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

首先,我必须确保传递必要的配置变量。 MEAN使用节点nconf包,默认情况下设置为限制从环境传递的变量。我不得不纠正这个问题:

<强>配置/ 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

注意:我重置了&#34; heirarchy指标&#34;到&#34; __&#34; (双下划线),因为它的默认值为&#34;:&#34;,这使得变量更难以从bash设置。请参阅此主题上的其他帖子。

现在的玉部分: 接下来需要渲染值,以便javascript可以在客户端获取它们。将这些值写入索引文件的简单方法。因为这是一个单页应用程序(角度),所以始终首先加载此页面。我认为理想情况下这应该是一个javascript包含文件(只是为了保持干净),但这对于演示来说很有用。

应用/控制器/ 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>        

从这一点来说,角度很容易使用代码。