0

我正在努力解决一个问题,我将通过一个简单的演示来解释。

PeopleCollection 中有以下非常简单的文档。

{  
    "_id" : "vxmLRndHgNocZouJg",  
    "fname" : "John" ,  
    "nicks" : [ "Johnny" , "Jo"]  
}

现在让我们考虑以下模板。基本上,我会显示用户名和带有输入字段的昵称列表,以添加更多昵称。

<head>
  <title>test</title>
</head>
<body>
  {{> name}}<br/>
  {{> nicks}}
</body>

<template name="name">
    <input type="text" value="{{fname}}"/>
</template>

<template name="nicks">
    {{#each nicks}}
        <div>{{this}}</div>
    {{else}}
        no nicks yet
    {{/each}}
    <input type="text" name="nicks"/>
    <input type="submit"/>
</template>

我的客户端javascript代码如下:

Template.name.fname = function() {
    return People.findOne({"fname" : "John"},{
        transform : function(doc) {
            return doc.fname;
        }
    });
}

Template.name.rendered = function() {
  console.log('Template "name" rendered!');
}

Template.nicks.nicks = function() {
  var john = People.findOne({"fname" : "John"});
  if(john) return john.nicks;
}
Template.nicks.events({
'click input[type="submit"]' : function () {
  var johnId = People.findOne({"fname" : "John"})._id; // demo code
  People.update(johnId,{
      $addToSet : {
          nicks : $('input[name="nicks"]').val()
      }
  })
}
});

我的问题是,在添加昵称(nicks文档中的字段更新)后,模板name被重新渲染(我知道是因为我 console.log 它)。当我查询People集合以提供name模板数据时,我使用transform选项,因此nicks字段的更改不应影响name模板产生影响。

Meteor 文档支持这一点:

游标是一种反应式数据源。当您第一次在反应式计算(例如,模板或自动运行)中使用 fetch、map 或 forEach 检索游标的文档时,Meteor 将注册对基础数据的依赖关系。任何更改游标中文档的集合都会触发重新计算。

name那么为什么要重新渲染模板呢?

4

1 回答 1

0

People由于您更改了集合,因此重新渲染了模板。

当您更改People集合时,Meteor 会自动假定它提供数据的所有内容都需要重新计算。(您的name模板通过Template.name.fname.

即使您转换了光标的输出,People集合也以某种方式发生了变化。查询是在使用转换之前完成的,换句话说,它不是查看的转换,而是整个集合。

Meteor 认为您的文档{'fname':'John'}可能有一些其他字段可能已更改,它需要重新查询它以检查(哪些nicks字段已更改)。然后在重新查询后应用转换。

此时您的 HTML 可能实际上并没有改变,只有当光标返回不同的东西时,html 才会被改变。

如果它在任何情况下都成为问题(即在不应该的情况下清除表单或更改 DOM),您可以使用这些{{#isolate}} {{/isolate}}块来确保只有它们内部的所有内容都被重新渲染,而外部没有任何内容。

于 2013-08-27T17:37:33.820 回答