Meteor: 在Blaze中强制整个模板重新渲染,以更新集合的内容

8

我有一个模板,其中DOM被更改,当保存到数据库时,我希望重新渲染模板。在Blaze之前,如果模板中有反应式变量,Meteor会重新渲染整个模板,但现在我该如何实现?

我在Iron路由器路线中设置了一个剪辑集合:

ClipsController = RouteController.extend({
    data: function() {
      clips = Clips.find({}, {sort: {created: 1}});
      return {clips: clips};
    }
});

还有一个关于剪辑的模板:

<template name="clips">
  {{#each clips}}
    {{> clip}}
  {{/each}}
</template>

然后,我有一个剪辑的模板:
<template name="clip">
  <article class="clip" id="{{_id}}">
    {{{content}}}
    <ul class="tags">
      {{#each tags}}
        <li><a href="/#{{this}}">#{{this}}</a></li>
      {{/each}}
    </ul>
  </article>
</template>

为这个模板编写一个脚本,它可以更改DOM并保存剪辑

Template.clip.events({
  'click .edit': function(event, template) {
    template.$('.tags li').each(function() {
      $(this).text($(this).text().replace(/^#(.*)/, "$1"));
    });
  },

  'click .save': function(event, template) {
    var data = {
      //...
    };

    Clips.update({_id: this._id}, data);

    // How to rerender the template ?
  }
});
5个回答

13

我不相信Blaze提供重新渲染整个模板的方法,因为Blaze的重点是进行细粒度的更新。

实现这一目标的一种快速而简单的方法是使用Session、模板辅助工具以及一个{{#unless}}块,将整个模板包裹起来,然后在更新之前将Session键设置为true,在更新后将其设置为false,从而导致{{#unless}}块中的所有内容重新渲染。

Template.clips.noRender = function(){
  return Session.get("noRender");
}

Template.clip.events({
  'click .edit': function(event, template) {
    template.$('.tags li').each(function() {
      $(this).text($(this).text().replace(/^#(.*)/, "$1"));
    });
  },

  'click .save': function(event, template) {
    var data = {
      //...
    };

    Session.set("noRender", true);

    Clips.update({_id: this._id}, data, function(){
      Session.set("noRender", false);
    });

    // How to rerender the template ?
  }
});

<template name="clips">
  {{#unless noRender}}
    {{#each clips}}
      {{> clip}}
    {{/each}}
  {{/unless}}
</template>

太聪明了!在我的情况下,使用稍微不同的编辑/查看模板并动态切换模板就解决了问题,但这是一个好技巧。 - Jide
1
聪明、可怕,但却非常有用。 :) - Adam Moisa
@AdamMoisa所说的。聪明、可怕,但是非常有用。 - blueren

2

我认为这可能是更好的解决方案,也符合Meteor的方式。

../clips.js

Template.clips.onRendered(function(){

   this.autorun(function(){
     Template.currentData();
   });

});

template.autorun(runFunc)

您可以在onCreated或onRendered回调函数中使用this.autorun来响应式地更新DOM或模板实例。您可以在此回调函数内部使用Template.currentData()来访问模板实例的响应式数据上下文。

http://docs.meteor.com/#/full/template_autorun


1

0

iron-router 的数据操作默认是响应式的。

   clips = Clips.find({}, {sort: {created: 1}});

替换为

  clips = Clips.find({}, {sort: {created: 1}}).fetch();

两者看起来都一样,或者我漏掉了什么? - Jide
第一个返回一个光标(是Meteor对象),另一个则给你一个结果数组。 - Hubert OG
我知道这一点,但在这种情况下,为什么我要返回一个数组而不是游标呢? - Jide

0

我认为更好的方法是使用 Tracker.afterFlush

例如:

Tracker.autorun ->
    Tracker.afterFlush ->
        # DOM is updated, why don't you do something here?

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接