【问题标题】:How to ignore changes not done by user?如何忽略用户未完成的更改?
【发布时间】:2018-04-07 22:33:05
【问题描述】:

我的视图模型中有一个 ko.observable,它附加到输入。当用户更改该输入的值(每个字符)时,我会运行 AJAX 调用,该调用会从后端下载建议。

当用户选择一项建议时,我想用所选值填充输入,但不发送 AJAX 调用。但是设置 observable 的值仍然会触发附加到 textInput 绑定的事件和调用函数。

如何在不触发 textInput 的情况下设置 observable 的值?

示例代码:

var name = ko.observable();
name.subscribe(nameChanged);

var nameChanged = function() {
    someService.post(name(), success, failure);
}

var someAction = function() {

    name("Test"); // I don't want to trigger AJAX call here
}
<input type="text" data-bind="textInput: name" />

【问题讨论】:

    标签: javascript knockout.js observable


    【解决方案1】:

    另一种选择是使用计算出的 observable 作为中介。 ajax 函数可以在计算的 write 事件中触发,以便直接写入 observable 绕过它。

    function viewModel(){
        var self = this;
        
        self.realName = ko.observable('test');
        
        self.Name = ko.computed({
            read: function(){
                return self.realName();
            },
            write: function(value){
                self.realName(value);
                nameChanged(value);
            }
        });
        
        function nameChanged(newName) {
            console.log("name changed:", newName);
        }
        
        self.modifyName = function(){
            self.realName(self.realName() + 'z');
        }
    }
    
    ko.applyBindings(new viewModel());
    <script src="https://cdnjs.cloudflare.com/ajax/libs/knockout/3.4.2/knockout-min.js"></script>
    
    
    <input type="text" data-bind="textInput: Name" />
    <br />
    <button data-bind="click: modifyName">Modify</button>

    【讨论】:

    • 我以两个 observables 结束:name 和 displayName。我还订阅了更改,当一个更改并且另一个不同时,第一个更新第二个。但现在我知道,变化来自哪里:如果 displayName 更新名称 - 来自用户,如果 name 更新 displayName,来自代码。不过,您的解决方案更优雅。
    【解决方案2】:

    可能在选择后在字段上设置一个特定的 CSS 类,并在 ajax 调用周围放置一些逻辑以检查该字段是否具有 CSS 类。

    【讨论】:

      【解决方案3】:

      您可以将 ajax 调用绑定到 ui 元素的 change 事件,而不是订阅 observable 的 change 事件。您将摆脱 name.subscribe(nameChanged); 并添加 event 绑定:

      data-bind="textInput: name, event: { changed: nameChanged }"
      

      【讨论】:

      • 这并不容易。我需要在每次值更改后触发 AJAX 调用,例如。在每次按键(包括粘贴、鼠标文本拖动等)之后,因为我正在请求该输入的自动完成建议。而changed 仅在输入失去焦点时被调用...
      【解决方案4】:

      一种有效但并不优雅的“老式”方式是暂时处置订阅,然后重新附加它:

      var myName = ko.observable();
      var nameSub = myName.subscribe(nameChanged);
      
      function nameChanged(newName) {
          console.log("name changed:", newName);
      }
      
      function changeWithoutLog() {
        nameSub.dispose();
        myName("Test");
        nameSub = myName.subscribe(nameChanged);
      }
      
      
      ko.applyBindings({ name: myName });
      <script src="https://cdnjs.cloudflare.com/ajax/libs/knockout/3.4.2/knockout-min.js"></script>
      
      
      <input type="text" data-bind="textInput: name" />
      <button data-bind="click: changeWithoutLog">change without post</button>

      【讨论】:

        猜你喜欢
        • 2020-02-22
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2022-06-23
        • 1970-01-01
        相关资源
        最近更新 更多