3

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

通读文档,看起来可能建议使用片段来执行此操作,但看起来需要将片段放入小部件中,然后将小部件放入页面中。

我了解模块分离的最佳实践问题,但我只是希望尽可能简单轻松地获取这些数据以供客户端使用(有点时间紧迫)。

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

(感谢您的帮助!在过去的几天里,我有几个撇号问题,但我认为这是帮助我填补将后端对象连接到前端的空白的最后一部分。)

\lib\modules\撇号页面\views\pages\home.html

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

\lib\modules\撇号页\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);
  }
 }
}
4

1 回答 1

4

如你所知,我在 P'unk Avenue 领导 Apostrophe 团队。

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

但是你也需要更加小心你的异步编程。现在你正在触发一个异步请求去获取一些文档;与此同时,您正在立即调用您的回调。这是不对的——回调的重点是,在您真正拥有数据并准备好在模板中呈现它之前,您不会调用它。

这是对相关代码的更正:

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 投影,如果您想了解更多信息,请阅读这些投影。)

使用“超级模式”保持原有pageBeforeSend方法

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

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

另一种解决方案是遵循“超级模式”以确保该方法的原始版本也被调用:

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>

nunjucksjson过滤器将数组转换为 JSON,保证输出到这样的脚本标签是安全的。所以你最终在浏览器端的 JavaScript 中得到了一个很好的数组。

使用find适合内容类型的方法

您可以避免为获取正确类型的内容并检查已发布等而创建自己的标准对象而烦恼。相反,请考虑编写:

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

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

希望这有帮助!

于 2016-10-13T19:53:55.693 回答