我将一段代码从 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”( session 保存在客户端更新中,因此需要确保从一个全新的环境开始才能使测试有效)
我的理解是ReactiveDict是Session的直接替代品(实际上,这是Session的代码可在软件包中使用)。但是在这种情况下,它们的行为却大不相同。
我发现的唯一解决方法是使用已存在的人工变量强制react触发器
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
我的问题是
我想到的解决方法的唯一“改进”是允许“解决方法”在true和false之间交替,但是这会引起其他类型的问题,例如无法仅通过查找真实值进行迭代。
另外,必须注意不要过滤掉“解决方法”,因为这样就不会正确触发重新计算。例如,自动运行中的以下更改不起作用,因为get('workaround')永远不会运行。
if (k != "workaround") console.log("selected2", k, " : ", selected2.get(k))
最佳答案
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()
并且上面的代码应该工作。