【问题标题】:Meteor ReactiveDict doesn't trigger event on first insertMeteor ReactiveDict 在第一次插入时不会触发事件
【发布时间】:2015-05-07 11:51:42
【问题描述】:

我将一段代码从 Session 迁移到 ReactiveDict。经过一些调试后,当 { key : value } 对添加到字典时,ReactiveDict 似乎没有触发任何重新计算事件。

var selected = new ReactiveDict()
  Meteor.autorun(function() {
    for (var k in selected.keys)
      console.log("reactiveDict", k, " : ", selected.get(k))
})

Meteor.setTimeout(function () { selected.set('test', true) }, 1000)
Meteor.setTimeout(function () { selected.set('test', false) }, 2000)
Meteor.setTimeout(function () { selected.set('test', true) }, 3000)
Meteor.setTimeout(function () { selected.set('test', false) }, 4000)

该代码不打印任何内容,而以下代码有效

Meteor.autorun(function() {
    for (var k in Session.keys)
        console.log("session", k, Session.get(k))
})

Session.set('test', true)

它打印“会话测试为真”(会话跨客户端更新保存,因此需要确保从一个新环境开始以使测试有效)

我的理解是 ReactiveDict 是 Session 的替代品(实际上它是 Session 的代码可用于包中)。但在这种情况下,它们的行为非常不同。

我发现的唯一解决方法是使用已经存在的人工变量强制反应触发器

var selected2 = new ReactiveDict()
selected2.set('workaround', false)

Meteor.autorun(function() {
  for (var k in selected2.keys)
  {
    var v = selected2.get(k)
    if (k != "workaround") console.log("selected2", k, " : ", v)
  }
})

var selected2_set = function (key, value) {
  var w = (selected2.keys[key] == undefined)
  selected2.set(key, value)
  if (w) {
    selected2.set('workaround', true)
    selected2.set('workaround', false)
  }
}

Meteor.setTimeout(function () { selected2_set('test', true) }, 1000)
Meteor.setTimeout(function () { selected2_set('test', false) }, 2000)
Meteor.setTimeout(function () { selected2_set('test', true) }, 3000)

打印“selected2 test : true”,然后是 false,然后是 true

我的问题是

  • 观察到的 ReactiveDict 行为是功能还是错误?
  • 有更好的解决方法吗?

我想到的解决方法的唯一“改进”是允许“解决方法”在真假之间交替,但这会产生其他类型的问题,例如无法仅迭代寻找真值。

此外,必须小心不要将“解决方法”过滤掉,因为这样就不会正确触发重新计算。例如,自动运行中的以下更改不起作用,因为 get('workaround') 永远不会运行。

if (k != "workaround") console.log("selected2", k, " : ", selected2.get(k))

【问题讨论】:

    标签: javascript meteor


    【解决方案1】:

    keys 只是ReactiveDict 的一个属性,并且没有注册反应性依赖项,因此这种行为是预期的。在 current implementation (meteor v1.1) 中,没有一种简单的方法可以实现您正在寻找的内容。

    upcoming version 中,all 将设置对所有键的响应式依赖,因此这将起作用:

    Tracker.autorun(function() {
      _.each(selected.all(), function(value, key) {
        console.log(key + ":" + value);
      });
    });
    

    如果您现在想使用该版本,您可以将源下载到名为 lib/reactive-dict2.js 的文件中,并将对 ReactiveDict 的任何引用替换为 ReactiveDict2(当前为第 19 和 43 行 - 请注意这是关键部分或其他部分您的应用程序可能会中断)。然后你可以这样做来使用它:

    var selected2 = new ReactiveDict2()
    

    上面的代码应该可以工作。

    【讨论】:

      猜你喜欢
      • 2020-11-22
      • 1970-01-01
      • 2015-12-05
      • 1970-01-01
      • 2011-01-07
      • 1970-01-01
      • 1970-01-01
      • 2019-12-04
      • 2010-10-31
      相关资源
      最近更新 更多