說說focus /focusin /focusout /blur 事件

事件觸發時間

focus:當focusable元素得到焦點時,不支持冒泡;
focusin:和focus同樣,只是此事件支持冒泡;
blur:當focusable元素失去焦點時,不支持冒泡;
focusout:和blur同樣,只是此事件支持冒泡;javascript

之前一直覺得全部事件都是支持冒泡的,都是能夠cancel的,查閱了[MDN上相關資料](https://developer.mozilla.org/en-US/docs/Web/Events)後,才發現有些事件支持冒泡,有些事件並不支持冒泡;有些事件有默認行爲(這類事件能夠cancel),有些事件壓根兒就沒有默認行爲(這類事件就不能 cancel )。從 MDN 上能夠清楚的看到 focusblur這2種事件不支持冒泡,支持冒泡的事件是focusinfocusouthtml

事件觸發順序

對於同時支持這4個事件的瀏覽器,事件執行順序爲focusin > focus > focusout > blur,代碼示例以下:java

html代碼chrome

<div class="parent">
    <input type="text" />
</div>
<div class="log"></div>

javascript代碼瀏覽器

function log(str){
  $('.log').append($('<div/>').text(str));
}

$('.parent')
    .focusin(function(){log('div focusin');})
    .focusout(function(){log('div focusout');})
    .focus(function(){log('div focus');})
    .blur(function(){log('div blur');});
$('input')
    .focusin(function(){log('input focusin');})
    .focusout(function(){log('input focusout');})
    .focus(function(){log('input focus');})
    .blur(function(){log('input blur');});

執行結果app

clipboard.png

從執行結果能夠看到4個事件的執行順序,同時也能夠看到 focus/blur是不支持冒泡的,因此.parent 元素綁定的focusblur事件回調並無觸發。this

focusin 與 focusout的瀏覽器支持

幾乎全部的瀏覽器都支持focusblur事件,但對於focusinfocusout 就不是這樣理想了。Firefox中不支持focusinfocusout事件;chrome和safari中只有經過addEventListener方式綁定事件才能正常使用,其餘方式綁定都不行;spa

面對這樣的瀏覽器支持彷佛很頭痛,慶幸的是jQuery對focusinfocusout作了兼容,使用$.focusin$.focusout實現事件綁定,在全部瀏覽器中都支持;代理

focusblur如何實現事件代理

事件代理簡單來講就是將子元素事件綁定在祖先元素上,之因此可以這樣作,得益於標準事件模型的捕獲和冒泡。咱們知道在標準事件模型中,一個事件的觸發會經歷三個階段:捕獲階段+目標階段+冒泡階段,有了捕獲和冒泡才能實現事件代理。由前面介紹可知,focusblur不支持冒泡,但其支持捕獲,但 IE 中事件模型沒有捕獲只有冒泡,因此在非IE瀏覽器中能夠經過在捕獲階段進行事件綁定實現事件代理。那麼針對IE瀏覽器怎麼實現呢?經過支持冒泡的是focusinfocusout實現就能夠了。代碼示例以下:code

html 代碼

<form name="form">
  <input type="text" name="name" value="Your name">
  <input type="text" name="surname" value="Your surname">
</form>

javascript 代碼

function addColor(){
  this.style.background="red";
}
var form = document.forms['form'];
if (form.addEventListener) { // 非 IE 瀏覽器
  form.addEventListener('focus', addColor, true);
}else{  // IE
  form.onfocusin = addColor
}

哪些元素是focusable的

在本文的第一小節提到了一個 focusable 元素的概念,我以爲有必要在這裏解釋一下什麼是focusable 元素。
默認狀況下,只有部分html元素能得到鼠標焦點如input,很大一部分html元素是不能得到鼠標焦點的如div,這些可以得到鼠標焦點的元素就是focusable 元素。要想一個元素得到焦點,能夠經過三種方式:

  • 鼠標點擊

  • tab 鍵

  • 調用focus()方法

那麼默認狀況下,哪些元素是focusable 元素

  1. window:當頁面窗口從隱藏變成前置可見時,focus 事件就會觸發

  2. 表單元素(form controllers):input/option/textarea/button

  3. 連接元素(links):a標籤、area標籤(必需要帶 href 屬性,包括 href 屬性爲空)

  4. 設置了 tabindex 屬性(tabindex 值非-1)的元素

  5. 設置了contenteditable = "true"屬性的元素

tabindex屬性

默認狀況下就能 focusable 的元素太少,若是想讓一個 div 元素成爲 focusable 的元素怎麼作呢?很簡單,設置 tabindex 屬性便可!
tabindex 有2個做用:

  1. 使一個元素變成 focusable
    只要在元素上設置了 tabindex 屬性,無論此屬性的值設爲多少,此元素都將變成focusable元素。

  2. 定義屢次按下 TAB 鍵時得到焦點的元素順序
    tabindex 屬性的值能夠正數、0、負數,當屢次按下TAB鍵,首先是tabindex爲正數的元素得到焦點,順序是:tabindex=一、tabindex=二、tabindex=三、tabindex=...,最後是tabindex=0的元素得到焦點。注意:tabindex爲負數的元素不能經過 TAB 鍵得到焦點,只能經過鼠標點擊或者調用focus()方法才能得到焦點。示例代碼以下:

<ul>
<li tabindex="1" onfocus="showFocus(this)">One</li>
<li tabindex="0" onfocus="showFocus(this)">Zero</li>
<li tabindex="2" onfocus="showFocus(this)">Two</li>
<li tabindex="-1" onfocus="showFocus(this)">Minus one</li>
<li tabindex="-2" onfocus="showFocus(this)">Minus two</li>
</ul>
相關文章
相關標籤/搜索