knockout.js:我是否可以在值更新之前捕获一个事件以停止更新?

ss2ws0br  于 2022-11-10  发布在  其他
关注(0)|答案(1)|浏览(156)

我知道我可以捕获输入框上的keydown事件,并从处理程序返回false,以阻止将按键应用于输入框。我想在更高的级别上使用敲除绑定来做一些事情,例如,我想阻止即将发生的更新,比如,在检查输入框中输入的值是否非法后,我不希望非法值应用到我的视图模型中,然后我不得不“手动”撤销它。我希望在视图模型以任何方式更改之前停止它。
我遇到的另一个真实的用例是,我想在输入应用到视图模型之前更改它的某些内容。例如,我可能想在更新它之前保存当前状态的副本。
如何在knockout框架中实现这一点呢?我可以处理mounsedown或focus事件,准备保存值,然后让更新发生,如果需要,再撤消更新,但我想停止更新本身。
下面是我的尝试:

<html>
  <head>
    <title>Initial Write Protect Example</title>
    <script src="knockout-3.5.0.debug.js" type="text/javascript"></script>
    <script type="text/javascript">
const data = {
    value: ko.computed({
        owner: this,
        read: function() { return "foo"; },
        write: function(x) { console.log("writing: " + x); debugger; }
    }),
};
let allowKey = true;

const changeFn       = function(x)  { console.log("changed: ",         x, data.value());  debugger; return false; };
const beforeChangeFn = function(x)  { console.log("about to change: ", x, data.value());  debugger; return false; };
const keydownFn      = function(x,event) { console.log("keydown: " + event.key + " allow? " + allowKey); return allowKey; };
const keyupFn        = function(x,event) { console.log("keyupn: "  + event.key);                         return false; };
    </script>   
  </head>
  <body>
    <p>
      <span>Current Value:</span>
      <span data-bind="text: value"></span>
      <br/>
      <input data-bind="value: value,
                        event:{
                            change:       changeFn,
                            beforeChange: beforeChangeFn,
                            keydown:      keydownFn,
                            keyup:        keyupFn
                        }"></input>   
    </p>
    <script type="text/javascript">ko.applyBindings(data);</script>
  </body>
</html>

从这里可以清楚地看到,虽然我可以阻止一个键生效(在调试器中将allowKey设置为false),但我无法阻止更改,没有发送beforeChange事件(在ko源代码中提到过一次,所以我想我应该尝试一下),并且change事件在ko.observable写入之后出现。所以,太晚了,当change事件触发时视图模型已经更改了。
我想我可以进入淘汰赛源代码来为自己修复一个很好的beforeChange事件,该事件的返回值为false将停止进一步的处理(并实际上将输入框中的值恢复为以前的值)。但我想知道是否已经有一些方法可以替代它?

更新

现在我已经了解到,可以为一个可观察对象订阅beforeChange事件:

observable.subscribe((newValue, eventName) => handle(newValue, eventName, 'beforeChange');

我在这里明确地给出了两个参数,以指出新值在这些处理程序中不可用。这是一个遗憾,因为我也需要新值。

ffvjumwh

ffvjumwh1#

下面介绍如何使用可写计算来防止更新传播到源可观察对象。
你可以使用一个扩展器来使它更容易重用。我写了一个扩展器来接受一个 predicate 函数,它接受一个字符串并返回true或false。根据你想用它做什么,你可能想支持一个 predicate ,它接受prevValuenextValue。这将导致validator(target(), str)
注意:如果输入字段没有响应,可能会给用户带来不好的体验,因此请确保向在输入字段中键入内容的用户提供反馈。
第一个

相关问题