javascript - Knockout Computed Observable 不更新 UI

标签 javascript asp.net knockout.js

我遇到了一个问题,尝试将 knockoutJS 可观察对象动态更新为计算可观察对象不会更新 UI。

我已经在复选框上实现了父子依赖关系,遵循交互规则。

  1. 当父 Checkbox 被选中时,所有的子 Checkbox 都会被选中。
  2. 当父 Checkbox 未选中时,则所有子 Checkbox 均未选中。
  3. 当任何一个子 Checkbox 未选中时,则父 Checkbox 也应取消选中。
  4. 选中所有子复选框后,应选中父复选框。

现在我有一个场景,其中父子依赖行为是动态的,即只有当用户单击按钮时,以上规则才开始工作。

我有一个实现,其中父复选框绑定(bind)到一个可观察的属性,后来该属性被覆盖为一个新的 Computed Observable。 更改为 Computed Observable 后,前 2 条规则(规则 1 和 2)起作用,但最后 2 条规则(规则 3 和 4)停止起作用。我可以在调试器中看到返回值已正确返回,但它没有更新 UI。

为了演示我的问题,我创建了 2 个 JS fiddle

  1. 拨弄 https://jsfiddle.net/agalo/rjc1Lsbe/4/描述了父子关系规则运行良好的场景。在这种情况下,Computed Observable 属性最初是在对象上定义的,不会动态更改。这非常有效。
  2. 拨弄 https://jsfiddle.net/agalo/uc7yt9tw/4/描述了规则 3 和 4 不起作用的当前实现。在这种情况下,Observable 属性在单击按钮时被计算的 Observable 覆盖。因此,最初不会强制执行父子关系,但在单击按钮时会强制执行此关系。

我不是在寻找替代解决方案,但我有兴趣了解为什么第二个 fiddle 会出现这种行为。

function ViewModel(){
   var self = this;
   
   var childrenArray = [  {isSelected : ko.observable(true)},
   						  {isSelected : ko.observable(true)},
                          {isSelected : ko.observable(true)},
                          {isSelected : ko.observable(true)}];
   self.parentChildData = {
                            parentCheckBox: ko.observable(false),
                            children: ko.observableArray([])
                          };
   self.parentChildData.children(childrenArray);
   
   self.makeDependent = function(){
		self.parentChildData.parentCheckBox = ko.computed({

                    read: function () {
                        var anyChildUnChecked = ko.utils.arrayFirst(self.parentChildData.children(), function (childCheckBox) {
                                return !childCheckBox.isSelected();
                            });
                            var result = anyChildUnChecked == null;
							return result;
                        
                        //return false;
                    },

                    write: function (value) {
                                ko.utils.arrayForEach(self.parentChildData.children(), function (childCheckBox) {
                                childCheckBox.isSelected(value);
                            });
                    }
      })};
	  
     return self;	  
	  
}

ko.applyBindings(new ViewModel());
<script src="https://cdnjs.cloudflare.com/ajax/libs/knockout/3.4.1/knockout-min.js"></script>
<p>
Describes my current implementation for which Rule 3 and 4 are not working. In this case, the Observable property is overridden with the computed Observable on the click of the button. So, initially the parent child relationship is not enforced, but on click of button the relationship is enforced.
</p>

<p>
After clicking the button, the first 2 Rules (Rule 1 and 2) works but last 2 Rule (Rule 3 and 4) stops working. I can see in the debugger that the return value is correctly returned but it doesn't Update the UI.

</p>
<div id="parent">
parent <input type="checkbox" data-bind="checked:parentChildData.parentCheckBox"/>
  
  <br/>
  <div id="child">
  Child
<!-- ko foreach: parentChildData.children -->
    <input type="checkbox" data-bind="checked:isSelected"/>
   <!-- /ko -->
  </div>
    <br/>
  <input type="button" value="Make dependent" data-bind="click:makeDependent">
  </div>

最佳答案

我想问题出在您的设置初始化时发生的事件序列。在您的实现中考虑以下流程 -

  • parentCheckBox首先定义为 observable属性(property) self.parentChildData .
  • self.parentChildData.children数组用子项初始化。
  • parentCheckBox现在更改为 computed observable .

我在这里看到的问题是 parentCheckBox 之前被要求对 self.parentChildData.children 中对 child 所做的更改使用react,这个子数组已经初始化,因此没有创建依赖关系,这就是为什么你没有得到你期望的行为。

所以,我稍微改变了你的代码流程并初始化了 self.parentChildData.childrenparentCheckBox之后被分配了 Angular 色 computedObservable (尽管它不会改变它最初的定义方式)。

self.parentChildData.parentCheckBox = ko.computed({

read: function() {
  var anyChildUnChecked = ko.utils.arrayFirst(self.parentChildData.children(), function(childCheckBox) {
    return !childCheckBox.isSelected();
  });
  var result = anyChildUnChecked == null;
  return result;

  //return false;
},

write: function(value) {
  ko.utils.arrayForEach(self.parentChildData.children(), function(childCheckBox) {
    childCheckBox.isSelected(value);
  });
}
});

self.parentChildData.children(childrenArray); //values are pushed here

此外,这消除了对 self.makeDependent 的需要函数,虽然我也很奇怪这个函数是如何在仍然是self.parentChildData.children的情况下让它工作的在 computed 之前已经有值了已创建 :-)

已更新 fiddle .

关于javascript - Knockout Computed Observable 不更新 UI,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/41750539/

相关文章:

Javascript if else 语句具有多个或以下条件

Javascript 不更新 h :inputHidden 的值

asp.net - 使用 ConfigurationManager 从任意位置加载配置

c# - 如何自定义 Forms Authentication cookie 名称?

javascript - 使用默认的 JavaScriptSerializer 将 DateTime 绑定(bind)到挖空 View 模型

javascript - 如何删除第 3 个之后的每个 {element}?

javascript - 将本地 mp4 文件转换为 fileURL 以进行视频 react

c# - 家庭网络上的 SignalR

javascript 数组序列化

mvvm - knockout 页面中的多个 View 模型不起作用