MeteorJS:按顺序加载...模板

时间:2017-03-10 03:51:47

标签: javascript meteor meteor-blaze

所以,基本上,我有一个包含多种类别照片的集合。我目前有这个设置来浏览类别并为每个类别加载模板:

{{#each categories}}
  {{>gallery collectionName=categoryName}}
{{/each}}

因此,这非常适合使用图库模板动态构建每个部分。

由于每个图库都有自己的图像集合,我在图库模板中添加了一个帮助函数来调用相应的集合,然后为每个集合图像添加到图库中。

(在图库模板内)

{{loadPhotos collectionName}}

现在,您可能会看到问题所在。

画廊div首先创建,空,然后一次创建,所有照片都添加到所有div中。

我希望,每个图库都会显示一个加载圈,直到所有照片都添加完毕,然后下一个图库开始加载照片,并且当加载所有照片时加载圈消失。这一直持续到所有类别都已加载。

我正在使用jquery添加照片和FlowRouter,如果这有帮助......

感谢您的时间和提供的任何解决方案!

1 个答案:

答案 0 :(得分:0)

我过去不得不做类似的事情,我能够做到这一点的方法是创建一种在模板和子模板之间进行通信的方法。执行此操作的主要方法是将回调函数传递给每个子模板,或者传递ReactiveVarReactiveDict或父级“正在侦听”的任何其他反应计算。我测试了下面的方法,它应该完美地适用于你所追求的目标。

首先是主要类别模板。

<template name="photoGallery">
  {{#each cat in categories}}
    {{> gallery collectionName=cat.name loadNow=loadTrigger isLoaded=loadedIndicator}}
  {{/each}}
</template>

以及相关的Javascript。请注意,对于此示例,我订阅了一个名为photoCategories的出版物,该出版物从名为Categories的集合中发布一组文档(其中包含name属性中的图库类别列表,我希望它们加载到loadOrder属性中。  您的具体情况可能有所不同。

import { Template } from 'meteor/templating';
import { Categories } from '../../../api/categories/categories.js';
import { ReactiveDict } from 'meteor/reactive-dict';
import { ReactiveVar } from 'meteor/reactive-var';

import './photoGallery.html';
import '../utils/loading-indicator.html';

Template.photoGallery.onCreated(function() {
  this.loadTrigger = new ReactiveDict('loadTrigger');
  this.lastLoaded = new ReactiveVar();
  this.loadOrder = [];

  // subscribe to category data and when complete build loading controls
  // in this example the collection that contains the categories is called
  // 'Categories' and each document contains a property called 'loadOrder'
  // to control the order to load the galleries
  this.subscribe('photoCategories', () => {
    // we are inside the 'onComplete' subscription callback
    Categories.find({}, {sort: {loadOrder: 1}}).forEach((category) => {
      // create a trigger for each gallery so we can communicate when to load
      // initialize each trigger to false for now
      this.loadTrigger.set(category.name, false);

      // we need to also keep track of our load order so we know which
      // gallery to trigger next
      this.loadOrder.push(category.name);
    });

    // now that everything is initialized, lets trigger the first gallery to load
    this.loadTrigger.set(this.loadOrder[0], true);
  });

  // re-runs everytime a gallery is finished loading
  this.autorun(() => {
    // get which gallery just finished loading
    var lastLoaded = this.lastLoaded.get();
    var lastLoadedIndex = this.loadOrder.indexOf(lastLoaded);

    // make sure we have more galleries to load
    if (lastLoadedIndex + 1 < this.loadOrder.length) {
      // get the next gallery to load
      var loadNext = this.loadOrder[lastLoadedIndex + 1];

      // trigger the gallery to load
      Tracker.afterFlush(() => {
        this.loadTrigger.set(loadNext, true);
      });
    }
  });
});

Template.photoGallery.helpers({
  // returns our photo gallery categories to iterate over in our template
  categories: function() {
    return Categories.find({}, {sort: {loadOrder: 1}});
  },

  // returns our ReactiveDict so we can communicate to our sub-template
  // galleries when they can load
  loadTrigger: function() {
    return Template.instance().loadTrigger;
  },

  // returns our ReactiveVar used to keep track of which gallery just loaded
  loadedIndicator: function() {
    return Template.instance().lastLoaded;
  },
});

基本上,我们在这里做的是订阅包含类别列表的出版物。然后我们构建一个加载触发器的字典,我们将用它来触发每个画廊加载。我们还需要定义最后加载的触发器,以便我们知道库加载完成的时间(并且可以触发下一个加载)。

为了确保这一切正常,我们需要确保将加载触发器和最后加载的触发器传递给库模板(这样它们就可以被触发加载并在完成后指示回来。)

现在让我们看看图库模板。

<template name="gallery">
  {{#if okToLoadNow collectionName}}
    {{loadPhotos collectionName}}
  {{else}}
    {{> loading_indicator }}
  {{/if}}
</template>

以及相关的javascript。

Template.gallery.helpers({
  // reactive checks if we are ok to load
  okToLoadNow: function(collectionName) {
    return Template.instance().data.loadNow.get(collectionName);
  },

  // contains logic that loads photos, renders them on the page, then triggers
  // back once the loading is complete
  loadPhotos: function(collectionName) {
    const instance = Template.instance();

    // insert the code that loads the photos and renders them on the page here!
    // if the logic is complete it probably makes more sense to put this in a sub-template
    // and put the logic in the `onRendered` callback

    // lets simulate loading by pausing for 3 seconds then communicate back
    // that we loaded
    Meteor.setTimeout(() => {
      instance.data.isLoaded.set(collectionName);
    }, 3000);
  },
});

在图库模板中,我们会显示一个加载指示器,直到我们被触发加载。一旦我们完成加载,然后我们指示(通过isLoaded触发器)我们完成了。为此,我们只传回刚刚加载的图库名称。

正如我之前提到的,我能够测试这种方法是否有效。你应该能够根据你的具体情况进行调整。

让我知道它是怎么回事!