模板刷新时的流星事件

时间:2014-08-22 15:44:08

标签: meteor

我正在研究使用Sessions定制分页的Meteor项目。呈现所述项目内容的模板使用ellipsis.js和highlight.js来进行一些DOM格式化。代码看起来像这样:

if (Meteor.isClient) {
    Meteor.startup(function () {
        Session.setDefault("homePageSize", 10);
        Session.setDefault("homePageStart", 0);
    });
}

Template.home.articlesPaginated = function() {
    return Articles.find({published: true}, {sort: {post_date: -1}, skip: Session.get("homePageStart"), limit: Session.get("homePageSize")});
}

Template.home.rendered = function() {
    // Setup ellipsis
    $('.ellipsis').dotdotdot({
        ellipsis: '...',
        wrap: 'word',
        fallbackToLetter: true,
        after: $('a.blog_continue')
    });

    // Setup highlight.js
    $('pre code').each(function(i, block) {
        hljs.highlightBlock(block);
    });
}

Template.home.events({
    'click .next': function(event) {
        var offset = Session.get("homePageStart") + Session.get("homePageSize");
        if (offset < 0) {
            offset = 0;
        }
        Session.set("homePageStart", offset);
    },
    'click .prev': function(event) {
        var offset = Session.get("homePageStart") - Session.get("homePageSize");
        if (offset < 0) {
            offset = 0;
        }
        Session.set("homePageStart", offset);
    }
});

分页工作得很好,但是一旦模板重新渲染,我就会松开所有的ellipsis.js和highlight.js格式。我知道明显的原因是DOM已经改变,并且因为Template.render只在前面运行一次,并且在模板重新渲染时没有发生DOM更新没有被应用。那么,在模板完成后触发ellipsis.js和highlight.js的最佳方法是什么,以便每次模板重新渲染时都会重新调用它?

2 个答案:

答案 0 :(得分:2)

基本上,您需要监听Articles集合中的更改,该集合是服务器数据库的客户端子集,其被剪裁为仅包含当前可见的分页文章。

当您检测到文章子集中的更改时,您需要重新启动ellipsis.jshighlight.js的初始化。

您可以按照以下方式重新组织代码:

首先,我们将游标声明定义为一个单独的函数,因为我们需要使用它两次:

function articlesPaginated(){
  return Articles.find({
    published: true
  }, {
    sort: {
      post_date: -1
    },
    skip: Session.get("homePageStart"),
    limit: Session.get("homePageSize")
  });
}

Template.home.helpers({
  articlesPaginated:articlesPaginated
});

然后在rendered回调中,我们需要设置一个依赖于此游标的反应计算,因此每当文章子集更新到新页面时,我们的计算将重新运行。

但是我们需要注意,我们在home模板上定义的帮助器返回相同的游标,因此它将被无效并在同一时间触发DOM刷新... JavaScript是单线程的{{1} } manual指出并发无效计算的执行顺序是不可预测的。

所以我们不能只是在计算中触发省略号/突出显示初始化代码,因为这个设置代码假定DOM已准备就绪,但是在这个精确的时刻我们不知道DOM操作是否刚刚发生或将要发生紧接着。

幸运的是,有一个Tracker.Computation方法允许我们在并发计算完成后执行代码,因此我们确信到那时DOM状态是正常的。

了解了所有这些含义之后,我们可以编写以下渲染回调:

Tracker.afterFlush

答案 1 :(得分:1)

如果您可以将Articles放入另一个模板,则可以在插入时单独应用格式。

Template.article.rendered = function () {
    // Setup ellipsis
    this.$('.ellipsis').dotdotdot({
        ellipsis: '...',
        wrap: 'word',
        fallbackToLetter: true,
        after: $('a.blog_continue')
    });

    // Setup highlight.js
    this.$('pre code').each(function(i, block) {
        hljs.highlightBlock(block);
    });
};

假设您的模板看起来像这样。

<template name="home">
  ...
  {{#each articlesPaginated}}
    {{> article}}
  {{/each}}
  {{> paginationControls}}
  ...
</template>

这样做的另一个好处是可以将格式设置为文章,而不是整个DOM。