【问题标题】:Knockout hasFocus binding with number input not working on Firefox带有数字输入的 Knockout hasFocus 绑定在 Firefox 上不起作用
【发布时间】:2016-06-16 23:16:09
【问题描述】:

我有一个包含货币值的输入字段。当输入字段没有焦点时,我试图显示格式化的货币金额。输入字段类型设置为数字。虽然这在 Chrome、IE 和 Edge 上运行良好;在 Firefox 上,输入文本框在获取后立即失去焦点。这是简化的jsfiddle

https://jsfiddle.net/nkkfmLmc/2/

这与http://knockoutjs.com/documentation/hasfocus-binding.html 的示例 2 类似,但数字字段除外。如果我将输入类型从数字更改为文本(但也失去了所有优点),问题就解决了。 任何指针或解决方法将不胜感激。

HTML:

<p>
    Name: 
    <b data-bind="visible: !editing(), text: '$'+amount(), click: edit">&nbsp;</b>
    <input type="number" min="0" max="100" step="1" data-bind="visible: editing, value: amount, hasFocus: editing" />
</p>
<p><em>Click the amount to edit it; click elsewhere to apply changes.</em></p>

JS:

function PersonViewModel(amount) {
    // Data
    this.amount = ko.observable(amount);
    this.editing = ko.observable(false);

    // Behaviors
    this.edit = function() { this.editing(true) }
}

ko.applyBindings(new PersonViewModel(51.22));

【问题讨论】:

    标签: javascript firefox knockout.js


    【解决方案1】:

    hasFocus 绑定与Document.activeElement 一起确定哪个元素是焦点:

    来源:https://github.com/knockout/knockout/blob/master/src/binding/defaultBindings/hasfocus.js#L17

    var ownerDoc = element.ownerDocument;
    if ("activeElement" in ownerDoc) {
      var active;
      try {
        active = ownerDoc.activeElement;
      } catch (e) {
        // IE9 throws if you access activeElement during page load (see issue #703)
        active = ownerDoc.body;
      }
      isFocused = (active === element);
    }
    

    在您的小提琴中逐步执行此绑定时,我注意到它返回 body 元素作为文档的 activeElement,使 isFocused 成为 false。

    在关于activeElement 的MDN documentation 页面上,我读到:

    注意:在 Mac 上,不是文本输入元素的元素往往不会获得焦点。

    在我看来,这表明number 输入中根本不支持此绑定。

    我建议:

    • 坚持文本输入并添加自定义上下按钮和按键监听器
    • 创建基于事件侦听器而不是 document.activeElement 的自定义绑定。

    淘汰赛开发人员可能有充分的理由坚持使用activeElement 方法。他们在他们的 cmets 中声明:

    // Where possible, ignore which event was raised and determine focus state using activeElement,
    // as this avoids phantom focus/blur events raised when changing tabs in modern browsers.
    // However, not all KO-targeted browsers (Firefox 2) support activeElement. For those browsers,
    // prevent a loss of focus when changing tabs/windows by setting a flag that prevents hasfocus
    // from calling 'blur()' on the element when it loses focus.
    // Discussion at https://github.com/SteveSanderson/knockout/pull/352
    

    所以选择第一个选项可能是明智的......

    【讨论】:

    • 得到了类似的诊断,但是,能够通过延迟 hasFocus 检查找到解决方法。感谢您的详细解释。
    • 有趣的发现。真的让我想知道淘汰赛绑定中发生了什么。我试图找出为什么 activeElement 没有及时设置,但无法重现该问题。在这个例子中,数字输入工作得很好......jsfiddle.net/0zobmbsn
    【解决方案2】:

    通过使用一个额外的 observable 来控制可见性并为控制焦点的 observable 添加一个节流阀来让它工作。 看起来 hasFocus 绑定检查是在元素变得可见之前发生的。

    https://jsfiddle.net/nkkfmLmc/8/

    JS:

    <p>
        Name: 
        <b data-bind="visible: !editingWrapper(), text: '$'+amount(), click: edit">&nbsp;</b>
        <input type="number" min="0" max="100" step="1" data-bind="visible: editingWrapper, value: amount, hasFocus: editing" />
    </p>
    <p><em>Click the amount to edit it; click elsewhere to apply changes.</em></p>
    

    HTML:

    function PersonViewModel(amount) {
        // Data
        var self = this;
        this.amount = ko.observable(amount);
        this.editing = ko.observable(false).extend({throttle:200});
        this.editingWrapper = ko.observable(false);
    
        // Behaviors
        this.edit = function() { self.editingWrapper(true);self.editing(true); }
    
        this.editing.subscribe(function(newVal){
            self.editingWrapper(newVal);
        })
    }
    
    ko.applyBindings(new PersonViewModel(51.22));
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2015-01-16
      • 1970-01-01
      • 2014-04-11
      • 2015-12-03
      • 2018-06-18
      • 2019-01-23
      • 2016-05-11
      • 1970-01-01
      相关资源
      最近更新 更多