快递 – 发送页面和自定义数据到一个单一的请求浏览器?

如何同时呈现一个页面并传输我的自定义数据到浏览器。 据我了解,它需要发送两层:首先与模板和第二与JSON数据。 我想通过骨干来处理这些数据。

正如我从教程expressbb app交互如下所示:

  1. res.render发送一个页面到浏览器
  2. document.ready触发jQuery.get到app.get('/post')
  3. app.get('/post', post.allPosts)发送数据到页面

这是三个步骤,如何做一个?

 var visitCard = { name: 'John Smit', phone: '+78503569987' }; exports.index = function(req, res, next){ res.render('index'); res.send({data: visitCard}); }; 

而我应该如何捕捉page- document.card这个variables?

我创build了我自己的小中间件函数,它将一个名为renderWithData的助手方法renderWithDatares对象。

 app.use(function (req, res, next) { res.renderWithData = function (view, model, data) { res.render(view, model, function (err, viewString) { data.view = viewString; res.json(data); }); }; next(); }); 

它包含视图名称,视图的模型以及要发送给浏览器的自定义数据。 它调用res.render但传入一个callback函数。 这指示express将编译后的视图标记作为string传递给callback函数,而不是立即将其传递给响应。 一旦我有视图string,我把它作为data.view添加到数据对象。 然后,我使用res.json将数据对象发送到浏览器,完成编译的视图:)

编辑:

与上述的一个警告是,该请求需要使用JavaScript,所以它不能是一个完整的页面请求。 你需要一个初始的请求来拉下包含javascript的主页面,这将使ajax请求。

这对于当用户通过AJAX导航到新页面时尝试更改浏览器URL和标题的情况非常有用。 您可以将新页面的部分视图连同页面标题的一些数据一起发送回浏览器。 然后,您的客户端脚本可以将部分视图放在页面所属的位置,更新页面标题栏,并在需要时更新URL。

如果您想要将一个完整的HTML文档以及一些初始JavaScript数据发送到浏览器,那么您需要将该JavaScript代码编译到视图中。 这绝对是可能的,但我从来没有find一种不涉及一些string魔法的方式。

例如:

 // controller.js var someData = { message: 'hi' }; res.render('someView', { data: JSON.stringify(someData) }); // someView.jade script. var someData = !{data}; 

注意:使用!{data}而不是#{data}因为jade默认转义HTML,所有的引号都变成" 占位符。

它看起来真的很奇怪,但它的工作原理。 基本上,你正在服务器上的一个JS对象,把它变成一个string,呈现该string进入编译视图,然后将其发送到浏览器。 当文档最终到达浏览器时,应如下所示:

 // someSite.com/someView <script type="text/javascript"> var someData = { "message": "hi" }; </script> 

希望这是有道理的。 如果我要重新创build我的原始帮手方法,以缓解第二种情况的痛苦,那么它看起来像这样:

 app.use(function (req, res, next) { res.renderWithData = function (view, model, data) { model.data = JSON.stringify(data); res.render(view, model); }; next(); }); 

所有这一切都是把你的自定义数据对象,为你的string,将其添加到视图的模型,然后呈现为正常的视图。 现在你可以调用res.renderWithData('someView', {}, { message: 'hi' }); ; 你只需要确保在你的视图中的某个地方抓取该数据string并将其呈现为variables赋值语句。

 html head title Some Page script. var data = !{data}; 

不要说谎,这整个事情感觉很糟糕,但如果它为您节省了一个额外的服务器之旅,那就是你在那之后,这就是你需要这样做。 也许有人可以更聪明地思考一些事情,但我不明白你会如何获得数据已经存在于第一次呈现的完整HTML文档中。

EDIT2:

这是一个工作的例子: https : //c9.io/chevex/test

您需要有一个(免费的)Cloud9账户才能运行该项目。 login,打开app.js,然后点击顶部的绿色运行button。

我的做法是发送一个cookie的信息,然后从客户端使用它。

server.js

 const visitCard = { name: 'John Smit', phone: '+78503569987' }; router.get('/route', (req, res) => { res.cookie('data', JSON.stringify(pollsObj)); res.render('index'); }); 

client.js

 const getCookie = (name) => { const value = "; " + document.cookie; const parts = value.split("; " + name + "="); if (parts.length === 2) return parts.pop().split(";").shift(); }; const deleteCookie = (name) => { document.cookie = name + '=; max-age=0;'; }; const parseObjectFromCookie = (cookie) => { const decodedCookie = decodeURIComponent(cookie); return JSON.parse(decodedCookie); }; window.onload = () => { let dataCookie = getCookie('data'); deleteCookie('data'); if (dataCookie) { const data = parseObjectFromCookie(dataCookie); // work with data. `data` is equal to `visitCard` from the server } else { // handle data not found } 

演练

在服务器上,您在呈现页面之前发送cookie,因此在加载页面时cookie可用。

然后,从客户端,你得到的cookie与我在这里find的解决scheme,并删除它。 cookie的内容存储在我们的常量中。 如果cookie存在,则将其parsing为对象并使用它。 请注意,在parseObjectFromCookie内部,您首先必须对内容进行解码,然后将JSONparsing为一个对象。

备注

  • 如果您要asynchronous获取数据,请小心呈现之前发送Cookie。 否则,你会得到一个错误,因为res.render()结束响应。 如果数据获取时间过长,则可能会使用另一个不能长时间保存渲染的解决scheme。 另一种方法是从客户端打开一个套接字并发送你在服务器上保存的信息。 看到这个方法。

  • 可能data不是一个cookie的最好的名字,因为你可以覆盖的东西。 使用更有意义的东西来达到你的目的

  • 我没有在其他地方find这个解决scheme。 我不知道是否由于某种原因不推荐使用Cookie,我不知道。 我只是认为它可以工作,检查它,但我没有用于生产。

使用res.send而不是res.render 。 它接受任何forms的原始数据:一个string,一个数组,一个普通的旧对象等。如果它是一个对象或对象数组,它会将它序列化为JSON给你。

 var visitCard = { name: 'John Smit', phone: '+78503569987' }; exports.index = function(req, res, next){ res.send(visitCard}; }; 

查看Steamer,一个为此目的而制作的小模块。

https://github.com/rotundasoftware/steamer