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

时间:2015-10-04 20:16:54

标签: meteor iron-router

我根据优秀的Meteor Kitchen项目生成的代码构建了一个小型流星应用程序。这段代码可以运行并将集合呈现给页面,但有一件事我很困惑。

代码的一个子集在这里:

router.js

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

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({})
      };
   }
});

服务器/酒吧/ articles.js

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


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

据我所知,此代码的工作原理如下:

(1)收藏通过 allArticles singleArticle 订阅发布 (2)ArticlesController订阅 allArticles
(3)ArticlesController中的数据功能将数据(从订阅?)提取到文章数组,然后将其暴露给Blaze模板。

我感到困惑的地方: 为什么我们需要在数据函数中执行 Articles.find({})?我们在哪里访问 allArticles 数据...我们似乎直接回到文章集合,如果我们只订阅 allArticles,那怎么可能?

3 个答案:

答案 0 :(得分:3)

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

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

Docs.当在服务器上执行此操作时,将创建一个Collection,并将其分配给变量名称Articles。 '文章'是用于在MongoDB中存储此集合的名称。

在客户端执行此操作时,会创建一个mini 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'。这些不是集合本身,而是指定服务器将发布的一组数据以及客户端可以订阅的规则。虽然这两个出版物从Server的文章集合返回数据,但是出版物可以从一个或多个集合返回数据,或者通过直接使用底层ddp协议,您可以发布来自另一个数据源(而不是mongodb)的数据。

接下来在客户端上订阅了一个集合:

Meteor.subscribe('allArticles')

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

此外,服务器将监视文章集合的变化,以及' allArticles'的结果集。发布更改,将这些更改作为更新发送给客户端。

接下来,您在Controller(客户端)中拥有数据功能。

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

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

这称为Articles.find而不是allArticles.find的原因是因为allArticles不是集合,而是客户端用于请求服务器发送数据的发布的名称,该名称存储在客户端mini mongo集合中命名文章。

答案 1 :(得分:1)

  

我们在哪里访问allArticles数据......似乎我们要回去了   直接到文章集合,如果我们如何可能   只订阅了所有文章?

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

  

为什么我们需要在数据函数中做一个Articles.find({})?

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

在控制器的数据功能中访问此信息只是为了避免在模板内部进行此操作。

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

  ArticlesController中的

数据函数提取数据(来自   订阅?)到文章数组然后暴露给   Blaze模板。

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

答案 2 :(得分:0)

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

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

如果您要展示列表文章,则需要订阅allArticles。如果有很多文章,您可以通过使用query projection限制字段的数量来提高应用的速度。