为什么在 Iron Router 控制器中调用 collection.find

Why call collection.find in an Iron Router controller

我基于优秀的 Meteor Kitchen 项目生成的代码构建了一个小型流星应用程序。此代码有效并将集合呈现到页面,但有一件事我感到困惑。

代码的一个子集在这里:

router.js

 this.route("articles", {path: "/articles", controller: "ArticlesController"});

文章控制器

this.ArticlesController = RouteController.extend({
   template: "Articles",

   onBeforeAction: function() {
        this.next();
    },

   action: function(){
      if (this.isReady()) {
         this.render();
      } else {
         this.render("loading");
      }
   },

   isReady: function() {
      var ready = true;
      var subs = [ Meteor.subscribe('allArticles') ];
      _.each(subs, function(sub) {
         if(!sub.ready())
            ready = false;
      });
      return ready;
   },

   data: function() {
      return {
         articles: Articles.find({})
      };
   }
});

server/pubs/articles.js

Meteor.publish('allArticles', function() {
  return Articles.find({});
});


Meteor.publish('singleArticle', function(articleId) {
  check(articleId, String);
  return Articles.find({_id: articleId});
});

据我了解此代码的工作原理,发生了以下情况:

(1) 合集通过 allArticlessingleArticle 订阅
发布 (2)ArticlesController订阅allArticles
(3) ArticlesController 中的 data 函数将数据(来自订阅?)提取到 articles 数组,然后将其暴露给 Blaze 模板。

我困惑的地方: 为什么我们需要在数据函数中做一个Articles.find({})?我们在哪里访问 allArticles 数据...似乎我们要直接回到 Articles 集合,如果我们订阅了怎么可能仅 allArticles ?

我需要更多地了解您的应用才能回答这个问题。您是只查看一篇文章,还是有一个页面列出所有文章?

如果您正在查看 单篇 文章,您需要订阅 singleArticle 出版物。

如果您要显示列表 篇文章,则需要订阅allArticles。如果有很多文章,您可以通过使用 query projection.

限制 字段 的数量来提高应用程序的速度

Where do we access the allArticles data ... it seems we are going back to the Articles collection directly and how is that possible if we have subscribed only to allArticles ?

您 return 将此作为数据对象的一部分,以便您可以在模板中访问它。在您的 Articles 模板中,您现在可以直接使用 {{#each articles}} 而无需辅助函数,因为 articles 是数据上下文的一部分。您还可以使用 this.articles.

Articles 模板助手中访问从您的控制器 data 部分编辑的文章 return

Why do we need to do a Articles.find({}) in the data function?

在您的控制器数据功能中执行的这些查询作用于客户端 minimongo 文章集合,而不是服务器。一旦信息从服务器发布,并且客户端订阅了它,客户端就可以在他们的 minimongo 实例中获得这些信息,但仍然需要以某种方式访问​​它。基本上,该出版物使信息可用,但 Articles.find({}) 为客户访问它。

在控制器的数据函数中访问此信息只是为了避免在模板中执行此操作。

我认为你的误解来自于你描述的第三步:

data function in the ArticlesController extracts the data (from the subscription?) to the articles array which is then exposed to the Blaze template.

数据函数从客户端的minimongo中提取数据,其中包含来自订阅的信息。 Minimongo 介于订阅和数据功能之间。

虽然你没有显示它,但我假设你的代码中有以下行,定义在将在服务器和客户端上执行它的地方:

  Articles       = new Mongo.Collection('articles');
/*CollectionName = new Mongo.Collection('DBCollectionName');*/

Docs. 在服务器上执行时,会创建一个 Collection,并将其分配给变量名 Articles。 'articles' 是用于在 MongoDB 中存储此 collection 的名称。

当在客户端执行此操作时,将创建一个迷你 mongo Collection。它最初没有任何文件。

接下来你只有服务器代码:

Meteor.publish('allArticles', function() {
  return Articles.find({});
});

Meteor.publish('singleArticle', function(articleId) {
  check(articleId, String);
  return Articles.find({_id: articleId});
});

Docs. 这定义了两个发布,'allArticles' 和 'singleArticle'。这些不是 Collection 本身,而是指定一组数据的规则,服务器将发布这些数据,客户端可以订阅这些数据。虽然这两个发布 return 数据来自服务器的文章 collection,但发布可以 return 来自一个或多个 collection 的数据,或者直接使用底层 ddp 协议可以发布来自另一个数据源的数据(不是 mongodb)。

接下来在你订阅的客户端上collection:

Meteor.subscribe('allArticles')

Docs. 此调用采用服务器上定义的发布名称 ('allArticles'),并订阅它。服务器然后执行发布功能,并通过 ddp 发送数据集 returned。此数据存储在上面创建的 Client-side Mini Mongo Collection 中,并命名为 Articles.

服务器还将监视文章 collection 的更改,如果 'allArticles' 发布的结果集发生更改,会将这些更改作为更新发送给客户端。

所以接下来你在你的控制器(客户端)中有数据功能。

data: function() {
  return {
     articles: Articles.find({})
  };
}

Docs. 这会设置渲染函数的数据上下文。

这里调用 Articles.find 而不是 allArticles.find 的原因是因为 allArticles 不是 collection,而是客户端用来请求服务器发送的出版物的名称数据,存储在名为 Articles.

的客户端 mini mongo collection 中