繁体   English   中英

knockout.js如何在ko.computed写入中取消confirm()后设置所选选项

[英]knockout.js how to set selected option after confirm() cancelled within a ko.computed write

我有一个带选项和默认文本的选择器元素:

self._selected = ko.observable();
self.option = ko.computed({
    read:function(){
        return self._selected;
    },
    write: function(data){
        if(data){
            if(confirm('are you sure?')){
                self._selected(data);
            }else{
                //reset
            }
        }
    }
});

<select data-bind="options: options, value:option, optionsCaption: 'choose ...'"></select>

这个问题:

  • 选择“一个”
  • 在确认点击取消
  • 所选选项仍然是“一个”仍在焦点下

它应该是“选择......”

jsbin在这里 ,它只在镀铬上测试过

问题是底层变量的值没有改变,因此没有事件告诉Knockout它的value与viewmodel不同步。

使用正常的observable,您可以调用valueHasMutated来指示发生了一些隐藏更改,但计算结果似乎没有。 但他们确实有notifySubscribers 实际上,您的示例非常类似于文档中的此示例

这是一个有效的例子:

 function vm() { const self = {}; self.options = ko.observableArray(['one', 'two', 'three']); self._selected = ko.observable(); self.option = ko.pureComputed({ read: self._selected, write: function(data) { if (data) { if (confirm('are you sure?')) { self._selected(data); } else { self.option.notifySubscribers(self._selected()); } } } }); return self; } ko.applyBindings(vm()); 
 <script src="https://cdnjs.cloudflare.com/ajax/libs/knockout/3.4.2/knockout-min.js"></script> <select data-bind="options: options, value:option, optionsCaption: 'choose ...'"></select> <div data-bind="text:_selected"></div> <div data-bind="text:option"></div> 

这里存在不对称性:

当您更改选择框的值时,DOM会立即更新并随后进行淘汰(当然,淘汰赛取决于DOM更改事件)。 因此,当您的代码询问“您确定吗?”时,DOM已经具有新值。

现在,当您将该值写入绑定到value:的observable时,viewmodel的状态不会更改。 并且当可观察到的更改时,knockout仅更新DOM。 因此DOM保持在选定的值,并且viewmodel中的绑定值是不同的。


最简单的方法是将旧值保存在变量中, 始终将新值写入observable,如果用户单击“否”,则只需恢复旧值。 这样就破坏了不对称性,DOM和视图模型保持同步。

 var AppData = function(params) { var self = {}; var selected = ko.observable(); self.options = ko.observableArray(params.options); self.option = ko.computed({ read: selected, write: function(value) { var oldValue = selected(); selected(value); if (value !== oldValue && !confirm('are you sure?')) { selected(oldValue); } } }); return self; }; // ---------------------------------------------------------------------- ko.applyBindings(new AppData({ options: ['one','two','three'] })); 
 <script src="https://cdnjs.cloudflare.com/ajax/libs/knockout/3.4.2/knockout-min.js"></script> <select data-bind="options: options, value: option, optionsCaption: 'Select...'"></select> <hr> <pre data-bind="text: ko.toJSON($root, null, 2)"></pre> 


这是一个淘汰扩展器的完美候选者,要求确认价值变化。 这样我们就可以将它重用于不同的observable并保持viewmodel的清洁。

 ko.extenders.confirmChange = function (target, message) { return ko.pureComputed({ read: target, write: function(newValue) { var oldValue = target(); target(newValue); if (newValue !== oldValue && !confirm(message)){ target(oldValue); } } }); }; // ---------------------------------------------------------------------- var AppData = function(params) { var self = this; self.options = ko.observableArray(params.options); self.option = ko.observable().extend({confirmChange: 'are you sure?'}); }; // ---------------------------------------------------------------------- ko.applyBindings(new AppData({ options: ['one','two','three'] })); 
 <script src="https://cdnjs.cloudflare.com/ajax/libs/knockout/3.4.2/knockout-min.js"></script> <select data-bind="options: options, value: option, optionsCaption: 'Select...'"></select> <hr> <pre data-bind="text: ko.toJSON($root, null, 2)"></pre> 

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM