流星和铁路由器的分页不重新渲染
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
方法,除非您尝试在路由代码中重新路由或处理该异常。
画廊 onCreated
和 helpers
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({});
}
});
注意:不需要在onCreated
和template.helpers
中定义你的助手
我真的很难理解这里发生了什么。我有模板
<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
方法,除非您尝试在路由代码中重新路由或处理该异常。
画廊 onCreated
和 helpers
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({});
}
});
注意:不需要在onCreated
和template.helpers