流星和铁路由器的分页不重新渲染

Pagination with meteor and iron router not re-rendering

我真的很难理解这里发生了什么。我有模板

<template name="gallery">
  <div>
    <a href="/">1</a><a href="/gallery/2">2</a><a href="/gallery/3">3</a>
  </div>
  {{#each art}}
    {{name}} 
  {{/each}}
</template>

然后我有这样的路线

Router.map(function() {
  this.route('/', {
    template: 'gallery',
    data: function() {
      var page = 1;
      return {
        page: page,
      };
    },
  });
  this.route('/gallery/:_page', {
    template: 'gallery',
    data: function() {
      var page = parseInt(this.params._page);
      return {
        page: page,
      };
    },
  });
});

关注 this article 我正在使用这样的模板订阅

  var G_PAGE_SIZE = 10;

  Template.gallery.onCreated(function() {
    var instance = this;
    var route = Router.current();
    instance.loaded  = new ReactiveVar(0);

    instance.autorun(function() {
      var pageId = parseInt(route.params._page);
      var page = pageId - 1;
      var skip = page * G_PAGE_SIZE;

      var subscription = instance.subscribe('artForGrid', skip, G_PAGE_SIZE);
      if (subscription.ready()) {
        instance.loaded.set(1);
      }
    });

    instance.art = function() {
      return Art.find({});
    };
  });

  Template.gallery.helpers({
    art: function() {
      return Template.instance().art();
    },
  });

它可以工作,但是当我单击其中一个更改路由的链接时,页面不会重新呈现

所以... some other answer on here 说那是因为在通过路由器和模板的路由上更改的数据之间没有反应性连接。

所以我尝试使用 route.state 作为 ReactiveDict(不确定它来自哪里)。如果它是 iron:router 的一部分或者它是 reactive-var

的一部分

反正我把代码改成了

Router.map(function() {
  this.route('/', {
    template: 'gallery',
    data: function() {
      var page = 1;
      this.state.set('page', page);  // <------------ADDED
      return {
        page: page,
      };
    },
  });
  this.route('/gallery/:_page', {
    template: 'gallery',
    data: function() {
      var page = parseInt(this.params._page);
      this.state.set('page', page);  // <------------ADDED
      return {
        page: page,
      };
    },
  });
});

onCreated

  Template.gallery.onCreated(function() {
    var instance = this;
    var route = Router.current();
    instance.loaded  = new ReactiveVar(0);

    instance.autorun(function() {
      var pageId = route.state.get('page'); // <--------- CHANGED
      var page = pageId - 1;
      var skip = page * G_PAGE_SIZE;

      var subscription = instance.subscribe('artForGrid', skip, G_PAGE_SIZE);
      if (subscription.ready()) {
        instance.loaded.set(1);
      }
    });

    instance.art = function() {
      return Art.find({});
    };
  });

  Template.gallery.helpers({
    art: function() {
      return Template.instance().art();
    },
  });

这也不管用,除非有时。为了调试,我在路由

中添加了一个 console.log
Router.map(function() {
  this.route('/', {
    template: 'gallery',
    data: function() {
      var page = 1;
      this.state.set('page', page);
      console.log("/root");  // <------------ADDED
      return {
        page: page,
      };
    },
  });
  this.route('/gallery/:_page', {
    template: 'gallery',
    data: function() {
      var page = parseInt(this.params._page);
      this.state.set('page', page);
      console.log("/gallery/" + page);  // <------------ADDED
      return {
        page: page,
      };
    },
  });
});

突然开始工作了!???!@!?我删除了 console.logs 并且它停止了

我也尝试在没有 console.logs

的情况下添加操作
Router.map(function() {
  this.route('/', {
    template: 'gallery',
    data: function() {
      var page = 1;
      this.state.set('page', page);
      return {
        page: page,
      };
    },
    action: function() {              // <- added
      var page = 1;                   // <- added
      this.state.set('page', page);   // <- added
      this.render();                  // <- added
    },                                // <- added
  });
  this.route('/gallery/:_page', {
    template: 'gallery',
    data: function() {
      var page = parseInt(this.params._page);
      this.state.set('page', page);
      return {
        page: page,
      };
    },
    action: function() {                      // <- added
      var page = parseInt(this.params._page); // <- added
      this.state.set('page', page);           // <- added
      this.render();                          // <- added
    },                                        // <- added
  });
});

那也不行。


更新

所以使用 Router.current().data().??? 似乎可以正常工作。现在是这个

Router.map(function() {
  this.route('/', {
    template: 'gallery',
    data: function() {
      var page = 1;
          // <--- removed this.state() stuff
      return {
        page: page,
      };
    },
         // <---- removed action stuff
  });
  this.route('/gallery/:_page', {
    template: 'gallery',
    data: function() {
      var page = parseInt(this.params._page);
          // <--- removed this.state() stuff
      return {
        page: page,
      };
    },
         // <---- removed action stuff
  });
});

帮手

  Template.gallery.onCreated(function() {
    var instance = this;
    instance.loaded  = new ReactiveVar(0);

    instance.autorun(function() {
      var route = Router.current();    // <----- Moved from 3 lines up
      var pageId = route.data().page;  // <--------- CHANGED
      var page = pageId - 1;
      var skip = page * G_PAGE_SIZE;

      var subscription = instance.subscribe('artForGrid', skip, G_PAGE_SIZE);
      if (subscription.ready()) {
        instance.loaded.set(1);
      }
    });

    instance.art = function() {
      return Art.find({});
    };
  });

  Template.gallery.helpers({
    art: function() {
      return Template.instance().art();
    },
  });

不知道这是现在 正确 还是我只是像 console.log 版本

那样走运

我的猜测是您的 autorun 函数没有被重新 运行 因为您没有使用任何反应变量。我不确定 Router.current()Router.current().data() 是否有反应,但如果不是,那么这对我来说很清楚地解释了这个问题。要对此进行测试,请尝试在您的 autorun 函数中放置一些控制台日志记录。

现在,我会提出一些可能对您有用的修改。

路由代码

重定向到 '/' URL 到 '/gallery/1' 以便您可以重新使用路由代码

Router.route('/', function(){
    this.redirect('/gallery/1');
});

将数据对象中的页码发送到您的模板很重要,这样我们就可以在 autorun 函数中使用此对象

Router.route('/gallery/:_page', {
    template: 'gallery',
    data: function() {
        return {
            page: this.params._page,
        };
    }
});

此外,您不需要使用 parseInt 方法,除非您尝试在路由代码中重新路由或处理该异常。

画廊 onCreatedhelpers

Meteor 提供了一个 Template.subscriptionsReady 帮助程序,因此您不必手动检查订阅是否已加载,除非您确实需要它。这是 Template.subscriptionsReady documentation

这是您的 onCreated 方法的简化版本,它使用由上面的路由代码构建的 template.data 对象。使用 autorun 包装器很重要,这样当 template.data 被您的路由器更改时它会重新 运行。

var G_PAGE_SIZE = 10;

Template.gallery.onCreated(function() {
    var instance = this;

    instance.autorun(function() {
        // access the data object built by your route code
        var pageId = instance.data.page;  

        var page = pageId - 1;
        var skip = page * G_PAGE_SIZE;

        instance.subscribe('artForGrid', skip, G_PAGE_SIZE);
    });

});

使用 template.helpers 方法定义对反应式数据源的访问。

Template.gallery.helpers({
    art: function() {
        return Art.find({});
    }
});

注意:不需要在onCreatedtemplate.helpers

中定义你的助手