Javascript 敲除hasFocus绑定,数字输入在Firefox上不起作用

Javascript 敲除hasFocus绑定,数字输入在Firefox上不起作用,javascript,firefox,knockout.js,Javascript,Firefox,Knockout.js,我有一个保存货币值的输入字段。当输入字段没有焦点时,我试图显示格式化的货币金额。输入字段类型设置为数字。而这在铬合金上效果很好;在firefox上,输入文本框在获取后立即失去焦点。下面是简化的JSFIDLE 除了数字字段外,这与示例2类似。如果我将输入类型从number改为text,问题就解决了(但也失去了所有优点)。 如有任何建议或解决办法,将不胜感激 HTML: hasFocus绑定使用Document.activeElement确定哪个元素处于焦点: 资料来源: 在您的小提琴中单步执行此

我有一个保存货币值的输入字段。当输入字段没有焦点时,我试图显示格式化的货币金额。输入字段类型设置为数字。而这在铬合金上效果很好;在firefox上,输入文本框在获取后立即失去焦点。下面是简化的JSFIDLE

除了数字字段外,这与示例2类似。如果我将输入类型从number改为text,问题就解决了(但也失去了所有优点)。 如有任何建议或解决办法,将不胜感激

HTML:


hasFocus
绑定使用
Document.activeElement
确定哪个元素处于焦点:

资料来源:

在您的小提琴中单步执行此绑定时,我注意到它将
body
元素返回为文档的
activeElement
,从而使
isFocused
变为
false

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

注意:在Mac上,非文本输入元素的元素往往无法获得分配给它们的焦点

对我来说,这表明在
number
输入中根本不支持这种绑定

我建议:

  • 坚持文本输入,添加自定义的上下按钮和按键侦听器
  • 创建基于事件侦听器的自定义绑定,而不是基于
    document.activeElement
击倒开发人员可能有很好的理由坚持使用
activeElement
方法。他们在评论中指出:

// 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绑定检查是在元素可见之前进行的

JS:


然而,由于得到了类似的诊断,他通过延迟hasFocus检查找到了解决办法。谢谢你的详细解释。有趣的发现。真的让我想知道在淘汰赛中到底发生了什么。我试图找出为什么
activeElement
没有及时设置,但无法重现问题。在本例中,数字输入工作正常。。。
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));
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);
}
// 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
<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>
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));