說說focus /focusin /focusout /blur 事件


轉載於:https://segmentfault.com/a/1190000003942014

事件觸發時間

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

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

事件觸發順序

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

html代碼

<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');});

執行結果

clipboard.png

從執行結果可以看到4個事件的執行順序,同時也可以看到 focus/blur是不支持冒泡的,所以.parent 元素綁定的focusblur事件回調並沒有觸發。

focusin 與 focusout的瀏覽器支持

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

面對這樣的瀏覽器支持似乎很頭痛,慶幸的是jQuery對focusinfocusout做了兼容,使用$.focusin$.focusout實現事件綁定,在所有瀏覽器中都支持;

focusblur如何實現事件代理

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

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=1、tabindex=2、tabindex=3、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>


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM