【问题标题】:MeteorJS ReactiveVar with database dataMeteorJS ReactiveVar 与数据库数据
【发布时间】:2015-09-15 09:02:58
【问题描述】:

显然,我在使用 ReactiveVar 时做错了,因为我无法让它按预期工作。

我试图通过调用返回用户名列表的 Meteor.call 方法来设置 ReactiveVar 的值。但是当用户名在应用程序的另一部分发生更改时,它不会更新。

我都试过了:

Template.qastatistics.created = function () {
  this.trackUsernames = new ReactiveVar(false);
  var instance = Template.instance();
  Meteor.call('trackUsernames', function (err, data) {
    instance.trackUsernames.set(data);
  });
};

和:

Template.qastatistics.helpers({
  users: function () {
  var usernames,
  instance = Template.instance();
  if (instance.trackUsernames.get() === false) {
    Meteor.call('trackUsernames', function (err, data) {
      instance.trackUsernames.set(data);
    });
  }
  usernames = instance.trackUsernames.get();
  ...

但是当数据库中的用户名发生变化时,它们都不会更新用户名列表。

ReactiveVars 甚至可以做到这一点,还是我完全误解了它们?

编辑:我提到的用户名不是来自 Meteor.users 集合,而是来自另一个包含用户名的集合的不同调用。

【问题讨论】:

  • 是的。我一次正确地获得了数据。但是当数据发生变化时它不会更新。

标签: meteor


【解决方案1】:

首先我会使用onCreated 函数而不是定义created。这有点可扩展,它是新的 API。 created 只是为了向后兼容而保留。

关于您的问题。你是对的,你似乎误解了ReactiveVars 的作用。它们是反应式数据源。这意味着当您在某些Tracker.autorun(又名反应式计算)中调用myReactiveVar.get 时,只要调用myReactiveVar.set,计算就会重新运行。

你说对了第一部分。空格键助手总是在他们自己的计算中运行。你错了认为方法调用是一个反应动作。这意味着,您可以调用trackUsernames 并再次设置trackUsernames ReativeVar,模板中的值将自行更新。但是一个方法只运行一次。它对反应性没有任何幻想。

一个方法调用只传输一次数据。另一方面,当您发布一组文档(如所有用户)时,它们将动态更新。每当该组已发布文档中发生更改时,它将被同步到客户端。 因此,一般来说,使用发布和订阅响应式同步数据是一个更好的主意。如果您想对同一件事使用一种方法,则需要进行某种轮询(这样您又回到了石器时代)。

实现您想要做的最简单的方法是使用Meteor.users.find().fetch()。正如the docs fetch 中所说,如果从反应式计算中调用,则为您获取的所有文档注册依赖项。

首先,您需要正确设置您的出版物,以便用户可以看到其他用户的用户名。我会把它留给你。然后你需要重新实现你的助手

Template.qastatistics.helpers({
  users: function () {
    var usernames = _.pluck(Meteor.users.find().fetch(), 'username');
...

【讨论】:

  • 感谢您的解释。我应该澄清用户名不是来自用户集合。我有一个很大的项目表,其中包含不同参数的用户名,例如“p4user”。我正在从该集合中提取不同的用户名以填充过滤器中的下拉列表...我想将此计算移至服务器,因为集合变得非常大...
  • @PredragStojadinović 你可以,方法和发布只是目的不同。方法是检索数据的一次性调用,其中发布的目的是通过 DDP 反应性地通知客户端进行更新。
  • @kyll 抱歉,我没听懂你的评论 :( 你说“你可以”,但我不明白你指的是什么......
  • 我的意思是,“您可以将此计算移至服务器”。在服务器上做任何你必须做的事情,然后如果这些操作的结果是反应性的,publish them 给客户端。
  • @kyll,到目前为止一切顺利。我唯一找不到的是从基础集合中删除项目时如何从已发布的自我中删除项目。它需要一个在我的情况下随机创建的 ID,不能是其他任何东西:(
【解决方案2】:

感谢@kyll 的建议,我设法通过发布我需要的数据得到了我想要的:

服务器:

cope.publish.usernamesID = Random.id();
Meteor.publish("itemsusernames", function () {
    self = this;

    var initializing = true;
    var handle = Items.find().observeChanges({
        added: function (id) {
            !initializing && self.changed(
                "itemsusernames",
                cope.publish.usernamesID, 
                Items.distinct("p4User"));
        },
        changed: function (id) {
            !initializing && self.changed(
                "itemsusernames",
                cope.publish.usernamesID, 
                Items.distinct("p4User"));
        },
        removed: function (id) {
            !initializing && self.changed(
                "itemsusernames",
                cope.publish.usernamesID, 
                Items.distinct("p4User"));
        }
    });
    initializing = false;

    self.added("itemsusernames", cope.publish.usernamesID, Items.distinct("p4User"));
    self.ready();

    self.onStop(function () {
        handle.stop();
    });
});

客户:

users: function () {
    var usernames = [],
        oUsernames = ItemsUsernames.find().fetch();

    if (!oUsernames[0]) return [];

    usernames = $.map(oUsernames[0], function (value, index) {
        if (!isNaN(index)) {
            return [value];
        }
    });
    ...

当然还有:ItemsUsernames = new Mongo.Collection("itemsusernames");

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2019-04-27
    • 2014-08-04
    • 1970-01-01
    • 1970-01-01
    • 2011-02-28
    • 2014-02-12
    • 1970-01-01
    • 2012-11-08
    相关资源
    最近更新 更多