将后端数据注入视图以便在客户端JS中使用

时间:2016-10-13 02:14:32

标签: apostrophe-cms

我想将一个文档列表返回给将在某个客户端JS中使用的数组。在我的apsotrophe-pages模块中,我有一个正在工作的apos.docs.find调用并返回我需要获取的文件。现在我有了这个文档数组,我需要将数据暴露给客户端JS。

通过阅读文档,看起来可能建议使用这些文件,但看起来需要将这些部分放入窗口小部件,然后放入页面中的窗口小部件。

我理解分离模块的最佳实践问题,但我只是希望尽可能简单轻松地将这些数据用于客户端(时间紧迫)。

我是否有一种简单易用的方法将此autoCompleteData数组公开给前端,因此我可以在客户端代码中执行类似下面的操作?

(感谢您的帮助!在过去的几天里我已经收到了几个撇号问题,但我认为这是帮助我填补将后端物体连接到前端的空白的最后一个问题。)

\ lib中\模块\撇号的页面\视图\页面\ home.html的

 <script>
   var page = apos.page;
   $('#displayDocs').text(page.autoCompleteData);
 </script>

\ lib中\模块\撇号的页面\ index.js

 module.exports = {
  types: [
     { name: 'default', label: 'Default Page' },
     { name: 'apostrophe-blog-page', label: 'Blog Index' },
  ],
  autoCompleteData: [],
  construct: function(self, options) {

    self.pageBeforeSend = function(req, callback) {

       let criteria = [
         {"type": "apostrophe-blog"}, 
         {"published": true}
       ];
       criteria = { $and: criteria };

       self.apos.docs.find(req, criteria).sort({ title: 1 }).toObject(function(err, collection){     
       self.autoCompleteData = collection;
    });

    return callback(null);
  }
 }
}

1 个答案:

答案 0 :(得分:1)

如你所知,我领导了位于P&#39; unk Avenue的撇号团队。

你非常接近解决问题。您只需将返回的数据附加到req.data,以便它在Nunjucks模板中作为data对象的一部分显示。

但是您还需要对异步编程更加小心。现在,您正在启动异步请求以获取一些文档;同时你正在调用你的回调。这是不对的 - 回调的关键是你不会调用它,直到你真正拥有数据并准备好在模板中呈现它。

以下是对相关代码的更正:

self.apos.docs.find(req, criteria).sort(
  { title: 1 }
).toArray(function(err, autocomplete) {
  if (err) {
    return callback(err);
  }
  req.data.autocomplete = autocomplete;   
  return callback(null);
});  

我所做的改变:

  • 我致电toArray,而不是toObject。您对此处的多个对象感兴趣。
  • 我在继续之前检查错误。如果有,我将其传递给回调并返回。
  • 我将数组分配给req.data.autocomplete,因此我的nunjucks页面模板及其扩展的布局可以看到它。
  • 我用null调用回调以表示之后的成功,然后返回。

请注意,在调用回调时,我总是使用return关键字。永远回归(ABR)。如果不是,您的代码将以您不期望的方式继续执行。

这段代码会遇到一些性能问题,因为如果这些代码有区域和连接等,它会获取很多信息。您应该考虑添加投影:

self.apos.docs.find(req, criteria, { title: 1, slug: 1 })...

为此目的添加您关心的任何其他属性到投影中的属性。 (这是标准的MongoDB投影,如果您想了解更多信息,请阅读这些内容。)

使用&#34;超级模式&#34;保留原始的pageBeforeSend方法

apostrophe-pages模块已经有pageBeforeSend方法,它确实很重要。如果你只是覆盖它,你将失去这项工作的好处。

一种解决方案是在项目中创建一个新模块,根本不会扩展另一个模块,并在那里引入pageBeforeSend方法。由于Apostrophe的pageBeforeSend机制调用了callAll,因此每个具有一个模块的模块都会调用它。

另一个解决方案是遵循&#34;超级模式&#34;确保调用该方法的原始版本:

var superPageBeforeSend = self.pageBeforeSend;
self.pageBeforeSend = function(req, callback) {
  // Do our things here, then...
  return superPageBeforeSend(req, callback);
};

将数据传递给浏览器中的javascript

回答你的下一个问题(:

在您的页面模板中,您现在可以写:

<script>
  var autocomplete = {{ data.autocomplete | json }};
</script>

json nunjucks过滤器将数组转换为JSON,保证可以安全地输出到这样的脚本标记中。所以你最终在浏览器端JavaScript中使用了一个很好的数组。

find方法用于适当的内容类型

您可以避免为创建自己的条件对象而烦恼,只是为了获得正确类型的内容并检查已发布的内容等。请考虑编写:

self.apos.modules['apostrophe-blog'].find(req, {}).sort()...

每个棋子模块都有自己的find方法,该方法返回一个自定义为该类型的游标,因此它可以更好地坚持已达到发布日期的内容以及您可能不会考虑的其他内容

希望这有用!