【问题标题】:What's the best way to display data when user input changes in Meteor (datepicker)?当 Meteor(datepicker)中的用户输入发生变化时,显示数据的最佳方式是什么?
【发布时间】:2016-02-18 00:20:55
【问题描述】:

我不知道该怎么说,但基本上我正在实现一个日期选择器,因此用户可以选择显示数据的范围。用户选择开始数据和结束日期,然后,我重新运行位于 lib 文件夹中的巨大函数,以重新运行并更改通过主页上的 Meteor 助手显示的所有数据。

用户选择的日期存储在 Session 变量中,这些变量可以在我想要的函数中访问。该函数运行,但客户端上未显示任何更改(但这些更改在控制台中是正确的,我可以通过我在整个函数中的console.log 语句看到所做的更改)。

这是 datepicker 的 onRendered 函数的样子:

Template.dashboard.onRendered(function(){
  // Date picker
  $(function() {

    function cb(start, end) {
        $('#reportrange span').html(start.format('MMMM D, YYYY') + ' - ' + end.format('MMMM D, YYYY'));

      var startDate = start.format('MMMM D, YYYY');
      Session.set("startingDate", startDate)
      var endDate = end.format('MMMM D, YYYY');
      Session.set("endingDate", endDate);
    }

  var firstDate = dates[0];
  var lastItem = dates.length-1;
  var lastDate = dates[lastItem]
    cb(moment(firstDate), moment(lastDate));

    $('#reportrange').daterangepicker({
        ranges: {
           'Last 7 Days': [moment().subtract(6, 'days'), moment()],
           'Last 30 Days': [moment().subtract(29, 'days'), moment()],
           'This Month': [moment().startOf('month'), moment().endOf('month')]
        }
    }, cb);

});

  });

Tracker.autorun:

  Tracker.autorun(function(){
    libFxn();
  });

libFxn() 是我在 Tracker 中调用的 lib 文件夹中相当大的函数。因此,每当 Session 变量之一由于用户输入而发生变化时,Tracker.autorun 就会触发并运行函数并更改值,我可以通过控制台看到这些值。但是,在客户端,我看不到更改。

这让我进退两难:我需要根据输入向用户显示结果数据的变化,但是:

1) 即使正在执行 lib 文件夹中的函数,客户端也看不到更改。 2)我不能使用document.location.reload(true);或以任何方式刷新页面,因为当页面刷新时,会话变量会恢复为默认值(这是我手头上dates数组的第一个日期和最后一个日期)。

所以我需要想办法将用户的日期输入数据发送到 lib 文件夹中的函数,以显示客户端/模板中的更改,如果页面必须是不涉及会话的刷新。

如果有人能给我提示或提示,我将不胜感激。

这是一个帮助器的示例,它与所有其他帮助器基本相同,只是它调用的不同变量(所有这些变量都在 libFxn() 函数中,并在那里填充并通过这些帮助器函数调用):

  WinRate: function(){
    if(Number((((wins/gamesPlayed))))){
      return numeral((wins/gamesPlayed)).format('0%');
    } else if(Number((((wins/gamesPlayed)))) === 0){
      return "0%"
    } else{
      return "n/a";
    }
  }

【问题讨论】:

  • 在持久性方面,如果更新集合不是一种选择,请考虑使用反应式本地存储包之一并将数据推送到 HTML5 本地存储层,这样您就可以在页面重新加载时将其持久化。
  • 感谢您的评论。我能够将日期保存在 MongoDB 集合中,然后在 lib 函数中调用它们,一切正常。我使用document.location.reload(true); 刷新页面并呈现数据。然而,现在唯一糟糕的是,它看起来真的很穷,我必须想办法让这看起来更流畅,更“反应灵敏”。
  • 您的模板和助手是如何设置的,您可以在这里或在 repo 中显示它们吗?
  • 我的助手基本上只是调用在 lib 文件夹中函数内部计算的变量的助手。我将在我的 OP 中留下一个示例,但从某种意义上说,它们都是这样的,它们调用或操作在 lib 文件夹本身的函数内部计算的变量。作为模板,它是一个具有自定义设计的标准模板,所有助手都通过{{Blaze}} 插入。我认为理论上,它应该呈现变化。
  • 您是否以任何方式使变量具有反应性?还是它们只是在文件中声明的变量?

标签: meteor


【解决方案1】:

从上面的 cmets 中,您不会使变量本身具有反应性。您可以使用Tracker.Dependency 执行此操作。

在您的 lib 文件中,您将希望使用 globalsDep = new Tracker.Dependency; 或类似的,您可能希望对函数的每种类型的结果都有一个,即如果您可以独立修改 10 个变量,那么您将需要 10 个,一个新的依赖项对于每一个,否则每次任何值更改时,您都将重新运行依赖于它们的每个助手。如果您希望一切都重新运行,当然只需使用一个:

globalsDep = new Tracker.Dependency;

您修改相关变量的每个地方(或者如果您只想要一个依赖项,则在函数的末尾)您需要告诉依赖项它已变为无效并需要重新计算

globalsDep.changed();

然后在您要重新运行的每个帮助程序中调用depends 函数:

globalsDep.depends()

您应该会在视图中看到它们立即奔跑。下面的简单例子:

/****************
** In Lib File **
****************/
globalsDep = new Tracker.Dependency;
xDep = new Tracker.Dependency;

x = 15;
y = 10;
t = 0;

myBigLongFunction = function(){
  x = x + 5;
  y = y + 1;
  t = x + y;

  console.log('Changing Values', x, y, t);
  globalsDep.changed();

  if (x > 20)
    xDep.changed();
}

/****************
** In JS File **
****************/
Template.main.helpers({
    testGlobalReactive: function(){
      globalsDep.depend();
      console.log('All vars rerun');
      return {t:t, x:x, y:y};
    },
    testXReactive: function(){
      xDep.depend();
      console.log('X rerun');
      return x;
    }
});

/****************
** In HTML File **
****************/
<template name="main">
  <div style="min-height:200px;width:100%;background-color:lightgrey;">
    {{#with testGlobalReactive}}
      X:{{x}}<br><br>
      Y:{{y}}<br><br>
      T:{{t}}<br><br>
    {{/with}}
    X Individual: {{testXReactive}}
  </div>
</template>

虽然我会警告不要以这种方式拥有客户端状态,但您最好利用集合的反应性并确保所有内容都通过它们与服务器同步,将此类数据存储在客户端上不会在任何地方持久存在,并且不能以任何方式信任,因为客户端可以随意修改全局变量。如果您已经在函数中从集合中设置此数据,请忽略最后一个,但您可能仍需要考虑在 Iron Router 数据字段中或直接从集合中访问模板级别的数据,因为默认情况下它将是响应式的,无需Tracker.dependency :D

【讨论】:

  • 感谢您的回复。我有数万行代码和数百个变量,因此现在将所有信息放入集合中是不可行的(也许将来我重构代码时)。以我的经验,数据渲染速度更快,显然使用更少的 MongoDB 存储。
  • 很公平,这将是很多工作!无论如何希望它有所帮助
猜你喜欢
  • 2010-11-10
  • 2023-01-21
  • 2014-06-21
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2021-03-07
  • 2010-09-29
相关资源
最近更新 更多