【问题标题】:Meteor reactive-var package is missing the equals() method, is this a bug?Meteor reactive-var 包缺少 equals() 方法,这是一个错误吗?
【发布时间】:2019-11-14 04:12:43
【问题描述】:

我正在学习 Meteor 中的反应式编程:

https://stephenwalther.com/archive/2014/12/05/dont-do-react-understanding-meteor-reactive-programming

我相信Session.equals(key, value) 背后的想法是记住反应变量和期望值之间的关联,这样更新只会在等式发生变化时传播到周围的代码。这样,如果我们有数百个依赖于变量的视图,则只有旧视图和新视图会在值更改时触发其更新代码。

请注意,如果我们调用Session.get(key) === value,则情况并非如此,因为每个视图的代码都会在变量更改时被调用。这将在文章的 Session.get 与 Session.equals() 部分下进一步讨论。

但我在使用反应性变量部分发现了不一致的地方:

Notice that a reactive variable, unlike the Session object, does not have an equals() method. Yes, that is a shame.

所以reactive-var 缺少equals()reactive-dictReactiveDict.equals()

我真的看不出排除ReactiveVar.equals() 的概念性原因。也许他们没有存储关联的上下文,或者可能存在一些范围界定或 Javascript 的其他问题阻止了这一点,我不完全理解。

所以我的问题是:这是一个错误吗?

我应该一直使用reactive-dict吗?在这种情况下,我会改变一切:

let myReactiveVar = new ReactiveVar();
...
if(myReactiveVar.get() === 'myValue')

更冗长(但更高效):

let myReactiveDict = new ReactiveDict();
...
if(myReactiveDict.equals('myReactiveVar', 'myValue'))

这将与Session.equals() 提供的功能相匹配。

另一种选择是使用我自己的equals() 方法扩展ReactiveVar 原型,或者在子类中继承它并提供MyReactiveVar.equals() 方法。如果有人可以提供示例来执行这些变通方法中的任何一种,我们可以将其作为拉取请求提交给 Meteor 维护者,这将不胜感激。

更新:我忘了提到 ReactiveVar 在其构造函数中确实采用了equalsFunc 可选参数。有可能将其作为反应代码块破解以部分实现equals() 功能而不扩展类。另外,这里是related issue on GitHub

更新:为了节省时间,这里是ReactiveVarReactiveDict.equals()的相关源码。我相信value 参数会转换为serializedValue,然后作为依赖项添加到ReactiveDict 中,但我仍然不明白为什么不能为ReactiveVar 做类似的事情。

【问题讨论】:

    标签: meteor equals


    【解决方案1】:

    ReactiveVar 没有 equals 方法的原因是因为 set 只会使计算无效,因为新值与当前值不同。

    设置 ReactiveVar 的当前值,如果 newValue 与旧值不同,则调用 get 的计算无效。

    const example = new ReactiveVar(0);
    
    Tracker.autorun(() => {
      console.log(example.get());
    });
    
    example.set(1); // logs 1
    example.set(0); // logs 0
    example.set(0); // doesn't log
    

    这与ReactiveDictequals 方法的行为类似。

    请注意,ReactiveDict 上的 set 不会以这种方式运行。调用set 会广播该值已更改。如果你想防止计算失效,那就是使用equals

    为 ReactiveDict 中的键设置值。通知任何侦听器该值已更改(例如:重绘模板,并重新运行任何 Tracker.autorun 计算,在此键上调用 ReactiveDict.get。)

    【讨论】:

    • 虽然这是真的,但它仍然没有回答我最初关于数百个视图的性能问题,这些视图在诸如 Session.equals(key, value) 之类的东西上收听,因此只有旧视图和新视图在会话值时调用它们的更新不再匹配所需的值。这可以通过ReactiveDict.equals(key, value) 实现,但不能通过ReactiveVar 实现,我还没有看到这样做的原因。非常感谢您的快速回复。
    • 是一样的。 set 仅在值更改时无效。如果反应变量发生变化,任何比较都会发生变化。当响应变量发生变化时,所有计算必须重新运行。他们中的任何一个都不能再平等了。和.equals一样,只是在不同阶段使计算失效。
    • 我不确定这是不是真的。如果我们有if(Session.equals('myVar', 0))if(Session.equals('myVar', 1))if(Session.equals('myVar', 2)),然后我们调用Session.set('myVar', 0) 然后Session.set('myVar', 1),那么只会运行 0 和 1 案例的代码。案例 2 的代码永远不会运行,因为 myVar 永远不会等于 2。而如果我们对其他数字使用 if(Session.get('myVar') === 0) 等等,那么任何 Session.get('myVar') 的所有代码都将被调用看看?
    • @ZackMorris 你是对的。在这里测试过:gist.github.com/joshleblanc/9d9509e0d6e33d24fa3e0653112ad772
    • 您好,感谢您抽出宝贵时间进行测试。如果我没看错,最初会调用所有 Tracker。然后console.log("var changed", v.get());v更改的任何时候被调用。而console.log("Running a === 1"); d.equals('a', 1) 仅在d0 to 11 to 2 转换时调用。 2 to 3 及以上不调用它。 Tracker d.equals('a', 2) 的工作方式类似,但适用于 2
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2020-04-06
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2023-03-29
    • 2013-07-23
    • 1970-01-01
    相关资源
    最近更新 更多