Meteor ReactiveDict第一次插入时不触发事件

6

我将一段代码从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)

它会打印“session 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的观察行为是特性还是bug?
  • 有没有更好的解决方法?

唯一我能想到的“改进”解决方法是允许'workaround'在true和false之间交替,但这会导致其他类型的问题,比如无法仅查找true值进行迭代。

此外,必须小心不要将'workaround'过滤掉,否则重新计算就无法正确触发。例如,autorun中的以下更改不起作用,因为get('workaround')永远不会运行。

if (k != "workaround") console.log("selected2", k, " : ", selected2.get(k))
1个回答

2
“keys”仅是“ReactiveDict”的属性,不会注册反应依赖项,因此这种行为是可以预期的。在当前实现(Meteor v1.1)中,没有一种简单的方法可以实现您要寻找的内容。
即将推出的版本中,“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()

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

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接