【问题标题】:Changing observable property of observable causes subscription on parent object to be triggered改变 observable 的 observable 属性会触发对父对象的订阅
【发布时间】:2014-11-01 16:58:58
【问题描述】:

我有一个 observable,比如 myValue。这个 observable 有一些属性,比如 id,也是 observable。我定义了一个自定义绑定来处理 myValue 的更改。 当我更改可观察属性 id 的值时,会触发 myValue 的自定义绑定。 这是非常不可取的,因为我的自定义绑定中的更新功能非常昂贵,而且我遇到了性能问题。 有没有办法防止父可观察对象与其未更新的子对象一起更新?

代码的核心部分

 //model opening, declaration, initialize...
 //In the model
 var self = this;
 this.myValue = ko.observable();
 this.myValue("Some value");
 this.myValue.id = 123;

 this.changeId = function() {
 self.myValue.id(111); //here the update for myValue is triggered
 }

 //After the model
 ko.bindingHandlers.customBinding = {
   init: function init(element, valueAccessor, allBindingsAccessor) 
     {/*nothing*/},
   update: function(element, valueAccessor, allBindingsAccessor) {
     /*expensive code*/
     console.log("I am being executed every time myValue.id() is changed...");
   }
 }

 //Then the model is applied...
 ko.applyBindings(model);

编辑:我暗示是否有办法改变 myValue.id 而不消除其可观察性。声明 myValue.id 不可观察可以解决问题,但我需要它是可观察的,所以我只会将此解决方案用作最后的更改。 无论如何,声明 myValue.id 不可观察会解决问题吗?我还没查过

【问题讨论】:

  • 是的,只是不要使用 observable。它仍然会获得双向绑定,但不会做任何通知。你必须自己做这些。相关小提琴:jsfiddle.net/841rsfk3
  • 是的,我尝试并看到了不可观察的属性,当更改时,不会触发对父可观察对象的订阅或绑定。没有任何方法可以防止将“泡沫”更新为父可观察对象吗?
  • 也许吧。不过,现在我认为您的代码甚至都不会运行,所以我不能肯定地说。我认为this.myValue.id = 123;self.myValue.id(111); 会爆炸。
  • 它在函数构造函数内部,所以在声明时,模型类似于 var model = new ModelConstructor();这样 this 引用新创建的模型对象“模型”,传递给 ko.applyBindings。很抱歉没有发布所有代码,我只是专注于我的问题。

标签: javascript knockout.js subscription observable


【解决方案1】:

如果我理解正确,你可以试试这样:

var myValue = ko.observable();
myValue.attributes = { id: ko.observable() };

那么对myValue.attributes.id 的更改不应该冒泡到myValue,因为两者之间有一个不可观察的对象,但我还没有测试过。

编辑

很遗憾听到这不起作用。我的最后一个想法,这是一个丑陋的 hack,将限制可观察的更新。

var myValue = ko.observable();
myValue.id = ko.observable()
               .extend({ rateLimit: { timeout: Integer.MAX_VALUE, method: "notifyWhenChangesStop" } });

这会在每次 id 发生更改时等待Integer.MAX_VALUEms,然后再传播更改,并在该时间有新更改时重置。在现实世界的解决方案中,这应该有效地禁用事件传播,但正如我所说,它是一种 hack。也许自定义扩展器的编写方式与 rateLimit 的编写方式大致相同,但我不知道 KO 来源。

【讨论】:

  • 很有意思,我准备先测试一下
  • 不,它不起作用。在您的答案中编辑了一个错字(id = -> id: )。 valueHasMutated 仍然传播到父 observable,跳过“attributes”层属性。很好的尝试,但不幸的是不起作用。
  • 实际上有点棘手,我相信所有这些速率限制的东西都会创建一个计时器。拥有像这样的多个控件可以很容易地用昂贵的多个计时器使浏览器超负荷。
  • 我完全同意。如果它很重要,我猜你真的需要检查源代码,看看你是否可以自定义它。
猜你喜欢
  • 1970-01-01
  • 2019-06-25
  • 2013-04-17
  • 2018-08-03
  • 1970-01-01
  • 1970-01-01
  • 2022-07-11
  • 2016-10-28
  • 1970-01-01
相关资源
最近更新 更多