表单焦点: focus/blur

表单焦点: focus/blur

当用户点击或按TAB键时元素会获得焦点。也有autofocusHtml属性可以设置元素获取默认焦点,当页面载入或其他方式。

获得焦点通常意味:准备在这里接受数据。所以此时我们可以写代码实现初始化或加载工作。

失去焦点时刻可能更重要(“blur”)。当用户在其他地方点击或按TAB键使焦点移动至下一个表单域,或其他方式。

失去焦点通常意味:数据已经进入。所以我们可以运行代码检查或保存数据至服务器等。

开发中使用焦点事件,有很多重要的特性。 本节详细进行说明。

focus/blur事件

事件focus在获得焦点时被调用,事件blur在失去焦点时被调用。 我们使用他们验证表单输入。

下面示例:

  • blur处理检查是否在文本域中录入email,如果不是展示错误。
  • focus负责隐藏错误消息(blur会再次检查)
<style>
      .invalid { border-color: red; }
      #error { color: red }
    </style>

    Your email please: <input type="email" id="input">

    <div id="error"></div>

    <script>
    input.onblur = function() {
      if (!input.value.includes('@')) { // not email
        input.classList.add('invalid');
        error.innerHTML = 'Please enter a correct email.'
      }
    };

    input.onfocus = function() {
      if (this.classList.contains('invalid')) {
        // remove the "error" indication, because the user wants to re-enter something
        this.classList.remove('invalid');
        error.innerHTML = "";
      }
    };
    </script>

现代HTML提供很多input属性用于验证:requiredpattern等。有时正好满足使用,Javascript可以实现更复杂的功能,如果检查正确,我们也可以自动发送改变后的数据至服务器。

focus/blur方法

方法elem.focus()elem.blur()设置元素获得或失去焦点.举例:如果值无效,则访问者无法立刻输入域:

<style>
      .error {
        background: red;
      }
    </style>

    Your email please: <input type="email" id="input">

    <script>
      input.onblur = function() {
        if (!this.value.includes('@')) { // not email
          // show the error
          this.classList.add("error");
          // ...and put the focus back
          input.focus();
        } else {
          this.classList.remove("error");
        }
      };
    </script>

除了FireFox(bug)所有浏览器都可以正常工作。

如果输入内容值输入域,然后尝试使用TAB或点击其他表单域,则onblur会再次让输入域获得焦点。

注意我们不能在onblur调用event.preventDefault()阻止失去焦点,因为onblur在所有元素失去焦点之后执行。

Javascript初始化时失去焦点

失去焦点有很多情况。

很多时候时用户点击其他地方,但有时Javascript自身也会引起,如:

  • alert弹出会获得焦点,所以会引起元素失去焦点(blur事件),当alert消失时,焦点会再次回来(focus事件)。
  • 如果dom删除某元素,那么会触发失去焦点事件,如果后来恢复,却不会获得焦点。

这些特性有时会引起focus/blur处理错误——因为不需要的触发。

当使用这些事件时需小心。如果想跟踪用户,初始化焦点-失去焦点,那么应该避免自身原因造成错误。

tabindex:允许任何元素获得焦点

默认情况下,很多元素不支持获得焦点。
浏览器之间有很多差异,但有一件事件总是正确的:用户交互元素支持focus/blur事件,如:<button>, <input>, <select>, <a>等。

另一方面,一些格式元素如<div>, <span>, <table>默认不能获得焦点,方法elem.focus()不工作,focus/blur事件永远不会触发。

但可以通过tabindex属性改变并实现。

该属性目的是指定当按tab键时,元素获得焦点的顺序。

如果有两个元素,第一个有tabindex="1",第二个有tabindex="2",焦点在第一个上,按tab键,焦点移动至第二个。

有两个特殊值:

  • tabindex="0" 使元素最后一个获得焦点.
  • tabindex="-1" 移动tab键,忽略该元素.

如果有tabindex,任何元素支持获得焦点
举例,有一个list,点击第一项,然后按tab:

Click the first item and press Tab. Keep track of the order. Please note that many subsequent Tabs can move the focus out of the iframe with the example.
    <ul>
      <li tabindex="1">One</li>
      <li tabindex="0">Zero</li>
      <li tabindex="2">Two</li>
      <li tabindex="-1">Minus one</li>
    </ul>

    <style>
      li { cursor: pointer; }
      :focus { outline: 1px dashed green; }
    </style>

顺序为:1 - 2 - 0(0总是最后),正常情况,<li>不支持获得焦点,但tabindex让其可以,事件和样式一样。

使用Javascript代码实现elem.tabIndex属性,效果一样。

代理:focusin/focusout

事件focusblur不启动。

举例:不能给<form>放置onfocus事件并使其高亮,如下:

<!-- on focusing in the form -- add the class -->
    <form onfocus="this.className='focused'">
      <input type="text" name="name" value="Name">
      <input type="text" name="surname" value="Surname">
    </form>

    <style> .focused { outline: 1px solid red; } </style>

上面示例不起作用,因为用户焦点在<input>上,焦点事件仅在input上,form不发出,所以form.onfocus永远不触发。

有两个解决方案:

第一,有趣的历史特征:focus/blur不触发,但是在捕获阶段传播。下面将工作:

<form id="form">
      <input type="text" name="name" value="Name">
      <input type="text" name="surname" value="Surname">
    </form>

    <style> .focused { outline: 1px solid red; } </style>

    <script>
      // put the handler on capturing phase (last argument true)
      form.addEventListener("focus", () => form.classList.add('focused'), true);
      form.addEventListener("blur", () => form.classList.remove('focused'), true);
    </script>

第二,有focusinfocusout事件,和focus/blur完全一样,但他们可以触发。
注意,他们通过elem.addEventListener赋值,不是on<event>.所以这是另一种可以正常工作:

<form id="form">
      <input type="text" name="name" value="Name">
      <input type="text" name="surname" value="Surname">
    </form>

    <style> .focused { outline: 1px solid red; } </style>

    <script>
      // put the handler on capturing phase (last argument true)
      form.addEventListener("focusin", () => form.classList.add('focused'));
      form.addEventListener("focusout", () => form.classList.remove('focused'));
    </script>

总结

事件focusblur触发元素获得/失去焦点事件。特别是:

  • 如果不触发,可以使用捕获状态代替或focusin/focusout
  • 大多数元素缺省不支持焦点,使用tabindex使他们可以获得焦点。

当前焦点元素是有效的,通过document.activeElement

  • 3
    点赞
  • 7
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值