Template.subscriptionsReady 禁用 onRendered 功能

Template.subscriptionsReady disables onRendered functionality

我正在 Template.templatename.OnRendered 中初始化日期选择器和表单验证。

 $('#dateAccepted').datepicker({
    endDate: new Date(),
    todayBtn: true,
    todayHighlight: true,
    autoclose: true
});

我正在 Template.templatename.onCreated 中进行订阅、collection 查询等。

Template.insertContract.onCreated(function () {
var self = this;
self.autorun(function() {
    self.subscribe('getContracts');
    self.subscribe('getSuppliers' ,function(){
        var suppliers = Supplier.find({}).fetch();
        var sOptions = createOptions('supplier','supplierName',suppliers, true);
        Session.set('supplierOptions', sOptions);
    });
    self.subscribe('getItems');
});

});

如果我将 Template.subscriptionsReady 放在我的模板上,日期选择器和表单验证将停止工作。没有错误消息。

这个问题被问了很多,但诚然很难搜索到。 是关于渲染轮播项目的类似问题。

这是正在发生的事情:

  1. 您的模板呈现并 onRendered 被调用。
  2. 您的订阅尚未准备就绪,因此未呈现日期选择器,但 (1) 中的初始化代码 运行s 就像它已经呈现一样。
  3. 最终呈现日期选择器。

一个可能的答案是在 sub-template 中呈现日期选择器。在 sub-template 的 onRendered 中你可以 运行 初始化代码,因为你可以保证它在 DOM 中。有关示例,请参阅上述问题的答案。

David 描述的很准确,sub-template 方法在某些情况下是一个不错的选择(我自己已经做过很多次)。

但有时感觉没有必要创建 sub-template,尤其是当它包含所有(或大部分)原始模板时。在这种情况下,您可以将订阅逻辑移至 onRendered 回调并使用 ReactiveVar 触发模板渲染。

这是一个例子:

Template.showStuff.onRendered(function() {
  this.isReady = new ReactiveVar(false);

  this.subscribe('mySubscription', () => {
    this.isReady.set(true);

    Tracker.afterFlush(() => {
      this.$('#dateAccepted').datepicker({
        endDate: new Date(),
        todayBtn: true,
        todayHighlight: true,
        autoclose: true
      });
    });
  });
});

然后定义一个助手以在模板中使用。

Template.showStuff.helpers({
  isReady: function() {
    return Template.instance().isReady.get();
  };
});

并使用上述帮助程序将依赖于订阅的内容包装到您的模板中。

<template name="showStuff">
  {{#if isReady}}
    ...datepicker and form stuff
  {{/if}}
</template>

请注意,您必须将日期选择器初始化内容放在 Tracker.afterFlush 中,因为只有在下一个刷新周期之后 DOM 才会真正呈现。如果您没有嵌入 afterFlush,那么将执行日期选择器初始化,但不会有任何影响,因为日期选择器实际上尚未在 DOM.

当 sub-template 感到被迫时,我无数次使用了这个选项。