在客户端JavaScript中访问Express.js局部变量


70

我想知道我是否做对了,如果不正确,你们会怎么做。

我有一个Jade模板,该模板需要呈现从MongoDB数据库检索到的一些数据,并且还需要访问客户端JavaScript文件中的该数据。

我正在使用Express.js并将数据发送到Jade模板,如下所示:

var myMongoDbObject = {name : 'stephen'};
res.render('home', { locals: { data : myMongoDbObject } });

然后在home.jade内部,我可以做类似的事情:

p Hello #{data.name}!

写出来:

Hello stephen!

现在,我想要的是也可以访问客户端JS文件中的此数据对象,以便在将其回发到服务器以更新数据库之前,只需单击一下按钮即可操作该对象。

通过将“数据”对象保存在Jade模板的隐藏输入字段中,然后在客户端JS文件中获取该字段的值,我已经能够实现这一点。

内部home.jade

- local_data = JSON.stringify(data) // data coming in from Express.js
input(type='hidden', value=local_data)#myLocalDataObj

然后在我的客户端JS文件中,我可以像这样访问local_data:

在myLocalFile.js内部

var localObj = JSON.parse($("#myLocalDataObj").val());
console.log(localObj.name);

但是,这种分类/解析业务令人感到混乱。我知道我可以将数据对象的值绑定到Jade模板中的DOM对象,然后使用jQuery提取这些值,但是我想访问客户端JS中从Express返回的实际对象。

我的解决方案是否最优,你们将如何实现?


4
我实际上是在几个月前创建了一个npm软件包来解决这个确切的问题:github.com/brooklynDev/JShare
BFree 2012年

Answers:


72

渲染完成后,仅将渲染的HTML发送到客户端。因此,不再有变量可用。您可以做的是,不要在输入元素中写入对象,而是将对象输出为呈现的JavaScript:

script(type='text/javascript').
    var local_data =!{JSON.stringify(data)}

编辑:显然,玉在第一个结束括号后需要一个点。


我仍然在脚本标记中看到未定义的“数据”。
braitsch 2012年

好的,这比我的输入字段解决方案好,因为它不需要将JSON字符串解析回一个对象或使用jQuery查找输入字段的值。
braitsch 2012年

这对我不起作用,我得到了[object Object]。我可能在使用stringify或parse在服务器端做错了吗?
2013年

4
@Costa取决于您的视图引擎,您可能无法从视图中调用JSON.stringify。相反,您应该在控制器中对其进行字符串化,然后将字符串作为变量传递{{{jsonData}}}(例如,在车把的情况下)。
汤姆(Tom)

建议的解决方案有效,我还建议使用express-expose,以更干净和集成的方式公开服务器端var。
xmikex83 2013年

13

我做的有点不同。在我的控制器中,我这样做:

res.render('search-directory', {
  title: 'My Title',
  place_urls: JSON.stringify(placeUrls),
});

然后在我的jade文件中的javascript中,我像这样使用它:

var placeUrls = !{place_urls};

在此示例中,它用于twitter bootstrap typeahead插件。然后,如果需要,您可以使用类似以下的内容来解析它:

jQuery.parseJSON( placeUrls );

还要注意,您可以忽略本地人:{}。


在关于遗弃当地人的笔记上+1,我不知道您可以这样做。
braitsch 2012年

1
排除本地人意味着什么?@braitsch
mathakoot

@iamrudra不必在render函数中用单词“ locals”作为本地对象的开头。res.render('home', { { data : myObject } })很好,res.render('home', { locals : { data : myObject } })尽管我可能还是建议您为清楚起见这样做。
braitsch

@braitsch:这对我来说是新事物。我在学校做过节点和表达项目,但从未使用过locals对象。您能给我指出正确的文档/阅读材料吗?
mathakoot

3

使用Jade模板:

如果要在包含的静态HTML文件上方插入@Amberlamps代码段,请记住指定!!! 在顶部的5中,为了避免样式被破坏,在views / index.jade中

!!! 5
script(type='text/javascript')
    var local_data =!{JSON.stringify(data)}

include ../www/index.html

这将在实际的静态HTML页面加载之前传递local_data变量,以便从一开始就可以全局使用该变量。

服务器端(使用Jade模板引擎)-server.js

app.set('views', __dirname + '/views');
app.set('view engine', 'jade');

app.get('/', ensureAuthenticated, function(request, response){
    response.render('index', { data: {currentUser: request.user.id} });
});

app.use(express.static(__dirname + '/www'));

1

您无需在渲染调用中传递locals变量,locals变量是globals。在您的哈巴狗文件调用中,请勿放置键表达式,例如#{}。只需使用类似: base(href=base.url)

这里base.urlapp.locals.base = { url:'/' };


-1

您听说过socket.io吗?(http://socket.io/)。从express访问对象的一种简单方法是在node.js和您的javascript之间打开一个套接字。这样,数据可以轻松地传递到客户端,然后使用javascript轻松进行操作。代码不必太多,只需socket.emit()来自node.js的代码和socket.on()来自客户端的代码。我认为这将是一个有效的解决方案!


18
这是用锤子打蜜蜂。它增加了很多请求,几乎没有。
Arnaud Rinquin 2012年

确实,在这种情况下,Socket.io过于强大。我正在寻找将JS变量从服务器传输到客户端脚本的最简便方法。
braitsch 2012年

3
大声笑,我有点像亚历克斯建议的,ba!啊,所有那些讨厌的当地人bam bam!
user1323136 2013年
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.