【发布时间】:2015-09-05 20:07:58
【问题描述】:
我正在写一个custom web component,它是为了互动。如何告诉浏览器这个自定义组件应该获得焦点?
我希望我的自定义元素……
- 可以聚焦(通过标签导航);
- 聚焦时可以接收按键;
- 可以与
:focuspseudo-selector匹配。
我没有使用任何外部库,只是普通的 HTML5 API。
【问题讨论】:
标签: html web-component
我正在写一个custom web component,它是为了互动。如何告诉浏览器这个自定义组件应该获得焦点?
我希望我的自定义元素……
:focus pseudo-selector匹配。我没有使用任何外部库,只是普通的 HTML5 API。
【问题讨论】:
标签: html web-component
基于我在this question 中找到的this demo,我有这个答案:
只需将tabindex 属性添加到您想要获得焦点的元素即可。
// Add this to createdCallback function:
if (!this.hasAttribute('tabindex')) {
// Choose one of the following lines (but not both):
this.setAttribute('tabindex', 0);
this.tabIndex = 0;
}
// The browser automatically syncs tabindex attribute with .tabIndex property.
点击元素将获得焦点。按选项卡将起作用。在 CSS 中使用 :focus 也可以。 keydown 和 keyup 事件有效,尽管 keypress 无效(但 it's deprecated anyway)。在 Chrome 44 和 Firefox 40 上测试。
还要注意this.tabIndex即使缺少HTML属性也会返回-1,但这与设置tabindex="1"有不同的行为:
<foo></foo>:没有tabindex 属性,该元素不可聚焦。<foo tabindex="-1"></foo>:该元素无法通过选项卡导航访问,但仍可通过单击获得焦点。参考资料:
【讨论】:
@Denilson,我想为您提供更多信息。
正如您所说,this.tabIndex = 0 在您的 web 组件不包含可聚焦元素时有效。如果是这样,它会变得更加复杂。
例如,如果您的组件包含一个或多个输入,则首先“整个”组件获得焦点,然后才在切换时,每个内部输入逐个获得焦点。这通常不是你想要的。通常,当组件获得焦点时,这意味着它的第一个输入会立即获得焦点。
此外,还有一个反向跳格问题。如果您的第一个输入具有焦点并且您按 SHIFT-TAB,则“整个”组件将获得焦点,并且您必须按两次 SHIFT-TAB 才能移动到上一个元素。
我发现这可以解决所有焦点和标签问题:
// At first, the component may get focus and accept tabbing.
createdCallback = function () { this.tabIndex = 0; }
// When the component gets focus, pass focus to the first inner element.
// Then make tabindex -1 so that the component may still get focus, but does NOT accept tabbing.
focus = function (e) { firstFocusableInnerElement.focus(); this.tabIndex = -1; }
// When we completely left the component, then component may accept tabbing again.
blur = function (e) { this.tabIndex = 0; }
注意:截至目前(2015 年 9 月),如果内部元素获得焦点,则 :focus 伪选择器不会匹配“整个”元素(仅在 Chrome 中测试)。如果发现这种行为是完全错误的。 focus 事件被触发,而 blur 事件未被触发。所以元素应该有焦点,对吧?我希望他们将来能改变这一点。
【讨论】:
如果可能且合适的话,我使用的一种非常实用的方法就是在我的自定义元素周围放置一个<button type='button'>。
这可能不适合您的解决方案,无论如何我都会为其他进入这个问题/问题的人提到它。
它处理所有焦点问题,包括焦点矩形等。
驯服<button> 的工作比看起来要少(尤其要考虑按钮更改的行高)
【讨论】: