简介

最近学习了一下flow-router的使用,对于/detail/:queryId这样的路由如何传递参数做一下总结。

场景还原

例如,我们网站的主页面显示很多图片,而详情页显示每个具体图片的详细信息,在我们的routes.js文件中,可以这样定义两个路由:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
// 主页面
FlowRouter.route('/main',{
name: 'main',
action: () => {
BlazeLayout.render('mainLayout', {main: 'main'});
},
subscriptions: function(){
this.register('mainpage',Meteor.subscribe('contents'));
},
});
// 详情页面
FlowRouter.route('/detail/:queryId',{
name: 'detail',
action: () => {
BlazeLayout.render('mainLayout', {main: 'detail'});
}
});

注意,上面我们通过subscriptions方法订阅了所有内容的数据库,这是flow-router提供的方法,具体用法见文档:flow-router

那么问题是如何得到每个:queryId,以及通过:queryId如何得到详细内容数据?

params的定义

首先在模板文件main.html中,定义两个模板:

1
2
3
4
5
6
7
8
9
<template name='main'>
{{#each contents}} {{> content}} {{/each}}
</template>

<template name='content'>
<a href="{{pathForDetail}}">
<img src="{{contents.url}}" alt="{{contents.name}}">
</a>
</template>

这里我们显示所有的图片,且每张图片都是一个指向详情页的链接。更多Blaze模板系统的用法,请参考官方文档:Blaze

然后我们要在main.js中定义一些helpers

1
2
3
4
5
6
7
8
9
10
11
12
Template.main.helpers({
contents() {
return Resources.find({}, {sort: {createdAt: -1}});
}
});

Template.content.helpers({
pathForDetail() {
const params = {queryId: this._id};
return FlowRouter.path('detail', params);
}
});

重点就在这里,我们通过const params = {queryId: this._id};这一条语句获得每张图片的queryId,并保存在params里,然后通过FlowRouter.path()方法生成完整的路径url。这样我们点击任意一张图片,就能进入到与之对应的详情页面。注意:queryId要和路由中定义的参数名保持一致;我们可以定义任何的params,不局限于id。

params的获得

publish.js中,我们定义了详情页的内容数据:

1
2
3
Meteor.publish('detail',(id) => {
return Resources.find({_id: id},{fields: {contents: 1}});
});

然后在detail.js中,我们要subscirbe这一数据,那这个id如何获得呢,这就需要刚才我们储存在params里的值了:

1
2
3
4
Template.detail.onCreated(function() {
const queryId = FlowRouter.getParam('queryId');
this.subscribe('detail', queryId);
});

只要我们需要图片的id,我们就可以从params里得到。接着我们还要定义helpers

1
2
3
4
5
6
Template.detail.helpers({
detail() {
const id = FlowRouter.getParam('queryId');
return Resources.findOne({ _id: id }) || {};
}
});

这样我们在模板中就可以通过detail这个helper,得到我们想要的任何数据。

更近一步

我们的detail方法还能改进,设想一下,我们需要在其他地方使用这个数据库的内容,比如其他的helper,或者events事件中,可是我们却没有地方获得。所以需要我们保存这个数据库的内容,代码可以改为:

1
2
3
4
5
6
7
8
9
10
Template.detail.helpers({
detail() {
const id = FlowRouter.getParam('queryId');
const detailContent = Resources.findOne({ _id: id }) || {};

const instance = Template.instance();
instance.content.set('content-detail', detailContent);
console.log(instance.content.get('content-detail'));
}
});

我们把数据存到名字叫contentReactiveDict中,这样我们在其他地方就能获取内容了,比如在events里:

1
2
const name = instance.get('content-detail').contents.name;
const url = instance.get('content-detail').contents.url;

注意,flow-router默认安装了这个包,我们只需要引入这个包,并且初始化:

1
2
3
4
5
6
import { ReactiveDict } from 'meteor/reactive-dict';

Template.detail.onCreated(function() {
this.content = new ReactiveDict();
......
});
最后 一张图
getData
getData