简体   繁体   English

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

[英]How to pass variable from jade template file to a script file?

I'm having trouble with a variable (config) declared in a jade template file (index.jade) that isn't passed to a javascript file, which then makes my javascript crash.我在 jade 模板文件 (index.jade) 中声明的变量 (config) 遇到了问题,该文件未传递给 javascript 文件,然后使我的 javascript 崩溃。 Here is the file (views/index.jade):这是文件(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')

Here is a part of my app.js (server side):这是我的 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));

And here is a part of my javascript file that crashes (public/javascripts/app.js):这是我崩溃的javascript文件的一部分(public/javascripts/app.js):

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

I'm running the site on development mode (NODE_ENV=development) on localhost (my own machine).我正在本地主机(我自己的机器)上以开发模式(NODE_ENV=development)运行该站点。 I'm using node-inspector for debugging, which told me that the config variable is undefined in public/javascripts/app.js.我正在使用 node-inspector 进行调试,它告诉我在 public/javascripts/app.js 中未定义配置变量。

Any ideas??有任何想法吗?? Thanks!!谢谢!!

It's a little late but...有点晚了但是...

script.
  loginName="#{login}";

This is working fine in my script.这在我的脚本中运行良好。 In Express, I am doing this:在 Express 中,我这样做:

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

I guess the latest jade is different?我猜最新的玉是不同的?

Merc.梅尔。

edit: added "."编辑:添加了“。” after script to prevent Jade warning.在脚本之后防止 Jade 警告。

#{} is for escaped string interpolation which automatically escapes the input and is thus more suitable for plain strings rather than JS objects: #{}用于转义字符串插值,它自动转义输入,因此更适合纯字符串而不是 JS 对象:

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

!{} is for unescaped code interpolation, which is more suitable for objects : !{}用于非转义代码插值,更适合对象

script var data = !{JSON.stringify(data)}
<script>var data = {"foo":"bar"} </script>

CAUTION : Unescaped code can be dangerous .注意:未转义的代码可能很危险 You must be sure to sanitize any user inputs to avoid cross-site scripting (XSS).您必须确保清理任何用户输入以避免跨站点脚本 (XSS)。

Eg:例如:

{ foo: 'bar </script><script> alert("xss") //' }

will become:会变成:

<script>var data = {"foo":"bar </script><script> alert("xss") //"}</script>

Possible solution: Use .replace(/<\\//g, '<\\\\/')可能的解决方案:使用.replace(/<\\//g, '<\\\\/')

script var data = !{JSON.stringify(data).replace(/<\//g, '<\\/')}
<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跳出变量: JSON.stringify转义引号
  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打破脚本标签:如果变量内容(例如,如果来自数据库,你可能无法控制)有一个</script>字符串,replace 语句会处理它

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

In my case, I was attempting to pass an object into a template via an express route (akin to OPs setup).就我而言,我试图通过快速路由(类似于 OP 设置)将对象传递到模板中。 Then I wanted to pass that object into a function I was calling via a script tag in a pug template.然后我想将该对象传递给我通过 pug 模板中的脚本标记调用的函数。 Though lagginreflex's answer got me close, I ended up with the following:虽然lagginreflex 的回答让我很接近,但我最终得到了以下结果:

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:在您的 node.js 路由中,将变量传递到名为window的对象中,如下所示:

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:然后在您的 pug/jade 布局文件中(就在block content之前),您可以像这样将它们取出:

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.当我的 layout.pug 文件加载每个 pug 文件时,我不需要一遍又一遍地“导入”我的变量。

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.这样,所有传递给window的变量/对象都“神奇地”最终出现在浏览器的真实window对象中,您可以在其中使用它们在 Reactjs、Angular 或 vanilla javascript 中。

Here's how I addressed this (using a MEAN derivative)这是我解决这个问题的方法(使用 MEAN 导数)

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. MEAN 使用 node nconf 包,默认情况下设置为限制从环境中传递哪些变量。 I had to remedy that:我不得不补救:

config/config.js:配置/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.注意:我将“层次指示符”重置为“__”(双下划线),因为它的默认值是“:”,这使得从 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.现在玉部分:接下来需要呈现值,以便javascript可以在客户端获取它们。 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.因为这是一个单页应用程序(angular),所以这个页面总是首先加载。 I think ideally this should be a javascript include file (just to keep things clean), but this is good for a demo.我认为理想情况下这应该是一个 javascript 包含文件(只是为了保持干净),但这对演示很有用。

app/controllers/index.js:应用程序/控制器/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:应用程序/视图/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:在我渲染的 html 中,这给了我一个不错的小脚本:

<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.从这一点来看,angular 很容易使用代码。

See this question: JADE + EXPRESS: Iterating over object in inline JS code (client-side)?看到这个问题: 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. Jade 不会将局部变量(或根本不做任何模板)传递给 javascript 脚本,它只是将整个块作为文字文本传递。 If you use the local variables 'address' and 'port' in your Jade file above the script tag they should show up.如果您在脚本标记上方的 Jade 文件中使用局部变量“地址”和“端口”,它们应该会显示出来。

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)我在上面链接的问题中列出了可能的解决方案,但您可以: - 将每一行作为未转义文本传入(!= 在每一行的开头),并在使用局部变量,或: - 通过 dom 元素传入变量并通过 JQuery 访问(丑陋)

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似乎 Jade 的创建者不想要多行 javascript 支持,如 GitHub 中的此线程所示: https : //github.com/visionmedia/jade/pull/405

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM