正确加载Template.templateName.rendered数据上下文

Properly loading Template.templateName.rendered data context

本文关键字:rendered 数据 上下文 templateName Template 加载      更新时间:2023-12-18

我有一个模板chartEditPreview,它在渲染回调触发后运行D3.js图表绘制函数。它看起来像这样:

Template.chartEditPreview.rendered = function() {
  drawChart(".chart-container", this.data);    
}

其中.chart-container是目标div,this.data是当前正在访问的DB中对象的数据。问题是,this.data经常返回null,看起来是随机的。这似乎与发布/订阅模式的工作方式有关——Iron Router(我正在使用)让模板渲染,然后将数据热推送到这些模板中。

我的问题(希望)很简单:在运行drawChart之前,我如何确保this.data实际上充满了DB数据?我应该用其他方式来做这件事,而不是在呈现的回调中调用它吗?

我想在路由期间将DB数据存储在Session变量中,并从呈现中调用它,但这似乎是一个额外的步骤,我不确定它是否能解决这个问题。图表也不是只在页面上呈现一次——它是交互式的,所以每次通过屏幕上的一个输入更新数据库对象时都需要重新绘制。

任何帮助都将不胜感激。谢谢


作为参考,以下是我的routes.js的样子:

Router.route('/chart/edit/:_id', {
  name: 'chart.edit',
  layoutTemplate: 'applicationLayout',
  yieldRegions: {
    'chartEditType': { to: 'type' },
    'chartEditPreview': { to: 'preview' },
    'chartEditOutput': { to: 'output' },
    'chartEditAside': { to: 'aside' },
    'chartEditEmbed': { to: 'embed' }
  },
  data: function () {
    return Charts.findOne({_id: this.params._id});
  },
  waitOn: function () {
    return Meteor.subscribe('chart', this.params._id);
  }
});

我的出版物.js:

Meteor.publish("chart", function (id) {
  return Charts.find({ _id: id });
});

这是Meteor的常见问题。虽然订阅可能已经准备好了(你应该像Ethaan显示的那样检查它),但这并不意味着find()函数实际上有时间返回一些东西。

通常我用一些防御代码来解决它,例如:

Template.chartEditPreview.rendered = function () {
  if(this.data)
    drawChart(".chart-container", this.data);
  // else do nothing until the next deps change
}

当然,这并没有达到应有的清洁程度,但据我所知,这是正确解决此类问题的唯一方法。

更新的答案在这种情况下,我们需要一个依赖项来触发数据更改时的重新运行。铁路由器为我们解决了这个问题:

Template.chartEditPreview.rendered = function () {
  var data = Router.current() && Router.current().data();
  if(data)
    drawChart(".chart-container", data);
  // else do nothing until the next deps change
}

this.ready()添加到data:function

 data: function () {
    if(this.ready()){
       return Charts.findOne({_id: this.params._id});
    }else{
       this.render('loading')
   }
  },

使用datawaitOn的可能有点棘手

Template.chartEditPreview.rendered = function() {
   Meteor.setTimeout(function(){
    drawChart(".chart-container", this.data);  
   },1000)  
}