使用 Blaze 编写智能组件

一些组件需要访问其数据上下文之外的状态,例如,通过订阅从服务器获取的数据或客户端存储的内容。如“数据加载”和“UI”文章中所述,在使用此类智能组件时,您应该谨慎并仔细考虑。

所有关于可重用组件的建议都适用于智能组件。此外

onCreated 订阅

您应该从 onCreated 回调函数(如果您有反应式变化的参数,则在 autorun 块中)订阅来自服务器的发布。在 Todos 示例应用程序中,在 Lists_show_page 模板中,我们根据当前 _id FlowRouter 参数订阅 todos.inList 发布。

1
2
3
4
5
6
7
Template.Lists_show_page.onCreated(function() {
this.getListId = () => FlowRouter.getParam('_id');

this.autorun(() => {
this.subscribe('todos.inList', this.getListId());
});
});

我们使用 this.subscribe() 而不是 Meteor.subscribe(),以便组件自动跟踪订阅何时就绪。我们可以使用此信息在 HTML 模板中使用内置的 {{Template.subscriptionsReady}} 助手,或者在使用 instance.subscriptionsReady() 的助手内使用。

请注意,在这个组件中,我们还访问了全局客户端状态存储 FlowRouter,我们将其包装在名为 getListId() 的实例方法中。此实例方法从 onCreated 中的 autorunlistIdArray 助手调用。

1
2
3
4
5
6
7
8
9
10
Template.Lists_show_page.helpers({
// We use #each on an array of one item so that the "list" template is
// removed and a new copy is added when changing lists, which is
// important for animation purposes.
listIdArray() {
const instance = Template.instance();
const listId = instance.getListId();
return Lists.findOne(listId) ? [listId] : [];
},
});

在助手函数中获取

如“UI/UX 文章”中所述,您应该在订阅数据的同一个组件中获取数据。在 Blaze 智能组件中,通常在助手函数中获取数据最简单,然后可以使用助手函数将数据传递到可重用的子组件中。例如,在 Lists_show_page

1
{{> Lists_show_page (listArgs listId)}}

listArgs 助手获取我们上面订阅的数据。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
Template.Lists_show_page.helpers({
listArgs(listId) {
const instance = Template.instance();
return {
todosReady: instance.subscriptionsReady(),
// We pass `list` (which contains the full list, with all fields, as a function
// because we want to control reactivity. When you check a todo item, the
// `list.incompleteCount` changes. If we didn't do this the entire list would
// re-render whenever you checked an item. By isolating the reactiviy on the list
// to the area that cares about it, we stop it from happening.
list() {
return Lists.findOne(listId);
},
// By finding the list with only the `_id` field set, we don't create a dependency on the
// `list.incompleteCount`, and avoid re-rendering the todos when it changes
todos: Lists.findOne(listId, {fields: {_id: true}}).todos()
};
}
});
在 GitHub 上编辑