【问题标题】:Why call collection.find in an Iron Router controller为什么在 Iron Router 控制器中调用 collection.find
【发布时间】:2016-01-01 11:30:46
【问题描述】:

我基于优秀的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({})
      };
   }
});

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 怎么可能? ?

【问题讨论】:

    标签: meteor iron-router


    【解决方案1】:

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

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

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

    在客户端执行此操作时,会创建一个迷你 mongo 集合。它最初不会包含任何文档。

    接下来你有服务器专用代码:

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

    Docs. 这定义了两个出版物,“allArticles”和“singleArticle”。这些不是集合本身,而是指定一组数据的规则,服务器将发布,客户端可以订阅。虽然这两个发布从服务器的 Articles 集合返回数据,但发布可以从一个或多个集合返回数据,或者通过直接使用底层 ddp 协议,您可以发布来自另一个数据源(不是 mongodb)的数据。

    接下来在您订阅集合的客户端上:

    Meteor.subscribe('allArticles')
    

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

    服务器还将监视 Articles 集合的更改,如果“allArticles”发布的结果集发生更改,则将这些更改作为更新发送给客户端。

    接下来,您的控制器(客户端)中有数据功能。

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

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

    之所以调用 Articles.find 而不是 allArticles.find 是因为 allArticles 不是一个集合,而是客户端用来请求服务器发送数据的发布名称,它存储在客户端 mini mongo 集合中命名文章。

    【讨论】:

    • 多么令人难以置信的答案。如果可以的话,我会投票两次。这部分对我来说完全有意义“存储在名为 Articles 的客户迷你 mongo 集合中。”。
    【解决方案2】:

    我们在哪里访问 allArticles 数据……看来我们要回去了 直接到文章集合,如果我们 只订阅了所有文章?

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

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

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

    在控制器的数据函数内部访问这些信息只是为了避免在模板内部进行。

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

    ArticlesController 中的数据函数提取数据(从 订阅?)到文章数组,然后暴露给 Blaze 模板。

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

    【讨论】:

      【解决方案3】:

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

      如果您正在查看单篇文章,您需要订阅singleArticle 发布。

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

      【讨论】:

      • 我不认为提问者打算询问何时使用每个出版物
      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2014-09-25
      • 1970-01-01
      • 2014-08-11
      • 2015-11-30
      相关资源
      最近更新 更多