我希望在Meteor中创建一个模板,该模板具有Tracker.autorun,该模板仅在文档的一部分发生变化时才会运行---但是当文档的其他部分发生变化时则不会。 所以这里是使用minimongo集合和template.autorun
的示例代码parent.html
{{#each items}}
{{> child}}
{{/each}}
child.html
<div>{{title}}</div>
<p>{{description}}</p>
Minimongo Collection
LocalProject.findOne() output:
"items": [
{
"title": "hi",
"description": "test"
},
{
"title": "hi 2",
"description": "test 2"
},
],
"otherstuff:{//etc}
child.js
Template.child.onRendered(function(){
this.autorun(function() {
var data = Template.currentData();
doSomething(data.title,data.description)
});
});
addnewitem.js
LocalProject.update(currentEditingProjectID,{ $push: { 'items': newItem }},function(error,result){
if(error){console.log(error)}
});
问题是,每当我运行addnewitem.js时,我的所有Template.child autoru都会执行,即使它们的反应数据源(Template.currentData())没有改变,除非它是我更新的特定项目。同样,如果我想更新现有项目,而不仅仅是向数组添加新项目,则每个项目的所有自动运行都会被执行。
有没有办法,使用这个模型,为autorun创建一个依赖于文档特定部分的反应性的依赖?
答案 0 :(得分:0)
这里有一个工具 - 3stack:embox-value提供反应隔离和值缓存。
使用您的示例,您可以将更改隔离到标题/描述,如下所示:
首先,添加包
meteor add 3stack:embox-value
meteor add ejson
然后,更新您的代码:
Template.child.onRendered(function(){
// creates a reactive data source, that only triggers "changes"
// when the output of the function changes.
var isolatedData = this.emboxValue(function(){
var data = Template.currentData();
return {title: data.title, description: data.description}
}, {equals: EJSON.equals})
this.autorun(function() {
// This autorun will only execute when title or description changes.
var data = isolatedData()
doSomething(data.title,data.description)
});
});
答案 1 :(得分:0)
我认为没办法就是使用自动运行。我会在每个项目上设置单独的反应依赖项,或使用observe
/ observeChange
。
<强> parent.html:强>
{{#each items}}
{{> child}}
{{/each}}
<强> parent.js:强>
Template.parent.helpers({
// Returns only item ids
items: function() {
return Items.find({}, { fields: { _id: 1 } });
}
});
<强> child.html:强>
{{#each items}}
{{#with item=getItem}}
<div>{{item.title}}</div>
<p>{{item.description}}</p>
{{/with}}
{{/each}}
<强> child.js:强>
Template.child.helpers({
getItem: function() {
// Get the item and set up a reactive dependency on this particular item
var item = Items.find(this._id);
// After item has been displayed, do something with the dom
Tracker.afterFlush(function () {
doSomething(item.title, item.description);
});
return item;
}
});
<强> parent.html:强>
{{#each items}}
{{> child}}
{{/each}}
<强> parent.js:强>
function do(item) {
Tracker.afterFlush(function () {
doSomething(item.title, item.description);
});
}
Template.parent.onCreated({
this.items = Items.find({});
this.handle = this.items.observe({
added: function(item) { do(item); },
changed: function(oldItem, newItem) { do(newItem); },
});
});
Template.parent.onDestroyed({
this.handle.stop();
});
Template.parent.helpers({
items: function() {
return Template.instance().items;
}
});
<强> child.html:强>
{{#each items}}
<div>{{title}}</div>
<p>{{description}}</p>
{{/each}}