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

Mic*_*ith 112 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')
Run Code Online (Sandbox Code Playgroud)

这是我的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));
Run Code Online (Sandbox Code Playgroud)

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

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

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

有任何想法吗??谢谢!!

Mer*_*erc 162

现在有点晚了......

script.
  loginName="#{login}";
Run Code Online (Sandbox Code Playgroud)

这在我的脚本中工作正常.在快递中,我这样做:

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

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

芝加哥商业交易所.

编辑:添加"." 在脚本之后防止Jade警告.


lag*_*lex 95

!{}用于非转义代码插值,更适合对象

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>
Run Code Online (Sandbox Code Playgroud)

这个想法是为了防止攻击者:

  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>
Run Code Online (Sandbox Code Playgroud)

  • 同意这是最好的答案,但我认为这不是逃避潜在危险字符串的正确位置。IMO 最好省略此代码中的 `replace` 调用,并将此值视为任何其他输入。JSON.stringify 保证生成有效的 javascript(或失败),并且在内存中有这个潜在危险的值后,您可以确保在使用前根据需要对其进行清理。 (2认同)

Kyl*_*len 6

在我的例子中,我试图通过快速路线(类似于OPs设置)将对象传递到模板中.然后我想将该对象传递给我通过pug模板中的脚本标记调用的函数.虽然lagginreflex的答案让我很接近,但我最终得到了以下结论:

script.
    var data = JSON.parse('!{JSON.stringify(routeObj)}');
    funcName(data)
Run Code Online (Sandbox Code Playgroud)

这确保了对象按预期传递,而不是需要在函数中进行反序列化.此外,其他答案似乎与原语一起工作正常,但当数组等与对象一起传递时,它们被解析为字符串值.


Sam*_*Sam 5

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

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

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

然后在您的pug / jade布局文件中(就在之前block content),将它们按如下方式取出:

if window
    each object, key in window
        script.
            window.!{key} = !{JSON.stringify(object)};
Run Code Online (Sandbox Code Playgroud)

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

这样,所有传递给window“魔术”的变量/对象最终都在window浏览器的真实对象中,您可以在Reactjs,Angular,...或普通javascript中使用它们。