天天看點

KeyPress 和KeyDown 、KeUp之間的差別

  前幾天,在寫完一個功能子產品上線測試的時候,出現了一個詭異的問題。input 框在輸入查詢内容之後,按Enter鍵居然有兩種不同的表現形式(input 框沒有綁定鍵盤事件),谷歌和火狐功能正常,但IE在按了Enter鍵以後居然自動調用方法。

頁面結構:标簽上沒綁定任何鍵盤事件,控制器内也沒有給元素綁定鍵盤事件。

<div class="search-input-tel search-input-visit-tel" >
    <input class="searchinput-tel searchinput-visit-tel" type="text" ng-model="private.keyWords" maxlength="20" placeholder="請輸入查詢資訊!"/>
</div>
           

表現形式:

KeyPress 和KeyDown 、KeUp之間的差別

,谷歌和火狐很正常,什麼事都沒發生

KeyPress 和KeyDown 、KeUp之間的差別

,IE上卻自動調用了一個方法,而且始終調用的同一個方法。

  搞得有點蒙圈,不曉得是咋回事。既然 input框 要調用鍵盤事件,那就調用吧,大不了我在标簽上面綁定定義好的鍵盤事件方法:

<div class="search-input-tel search-input-visit-tel" >
    <input class="searchinput-tel searchinput-visit-tel" type="text" ng-model="private.keyWords" maxlength="20" placeholder="請輸入查詢資訊!"
           ng-keypress="enterQuery($event,'query',1)" ng-change="changesData(private.keyWords)"/>
</div>
           

  鍵盤回車事件方法:

//Enter鍵功能
$scope.enterQuery = function (event,type,repetitionType) {
    var key =  window.event ? window.event.keyCode : event.which;       //擷取鍵盤碼;window.event.keyCode 擷取IE下的鍵盤碼,event.which擷取非IE下的鍵盤碼
    if (key === 13) {       //Enter鍵鍵盤碼為13
        try {
            if (window.event) { //ie
                $scope.clientsHeavy(type,repetitionType);
                window.event.returnValue = false;
            } else {    //非IE
                $scope.clientsHeavy(type,repetitionType);
                return false;
            }
        }
        catch (ex) {
        }
    }
};
           

  這下解決了 input框 回車自動調用方法的問題。

  現在傳回來看他們之間的差別,在此我用了 keypress 事件,而沒有用 keyup 事件,因為keyup事件在IE上和谷歌上表現形式又不一樣。同樣是執行 console.log("鍵盤碼:key="+ key);

  谷歌浏覽器:keypress 事件和 keydown 事件,以及 keyup 事件,三者執行結果一樣,控制台都會列印:   鍵盤碼:key=13

  IE浏覽器:keypress 事件和 keydown事件,控制台也都會列印:鍵盤碼:key=13 ;但是到了 keyup事件,控制台則不列印:鍵盤碼:key=13,這表示keyup事件并沒有執行我們自定義的方法,反而又出現了自動調用方法的情況。是以自己在這總結下,他們仨之間的差別,加深印象。

   

Windows窗體通過引發鍵盤事件來處理鍵盤輸入以響應Windows消息,大多數Windows窗體應用程式都通過處理鍵盤事件來以獨占方式處理鍵盤輸入。

1.按鍵的類型

  Windows窗體将鍵盤輸入辨別為 由按位Keys枚舉 表示的虛拟鍵代碼。使用Keys枚舉,可以綜合一系列按鍵以生成單個值,這些值與WM_KEYDOWN和WM_SYSKEYDOWNWindows消息所伴随的值相對應。另外,程式開發人員可通過處理KeyDown或KeyUp 事件來檢測大多數實體按鍵操作。字元鍵是Keys枚舉的子集,它們與WM_CHAR和WM_SYSCHAR Windows消息所伴随的值相對應,如果通過組合按鍵得到一個字元,則可以通過處理KeyPress事件來檢測該字元。

事件定義:

  1. KeyDown:在控件有焦點的情況下按下鍵時發生。
  2. KeyPress:在控件有焦點的情況下按下鍵時發生。(下面會說和KeyDown 的差別)
  3. KeyUp:在控件有焦點的情況下釋放鍵時發生。

2.鍵盤事件的順序

  一個控件上可能出現3個與鍵盤相關的事件,下面是這些事件發生的正常順序:

  • 使用者按“a”鍵,該鍵将被預處理和排程,同時會觸發KeyDown事件。
  • 使用者按住“a”鍵,該鍵将被預處理和排程,同時會觸發KeyPress事件。
  • 使用者松開“a”鍵,該鍵将被預處理和排程,同時會觸發KeyUp事件。

  但是KeyDown觸發後,不一定觸發KeyUp,當KeyDown 按下後,拖動滑鼠,則不會觸發KeyUp事件。

3.鍵的預處理

  像其他消息一樣,鍵盤消息是在窗體或控件的WndProc方法中處理的。窗體或控件在處理鍵盤消息之前,PreProcessMessage方法會調用一個或多個方法,這些方法可被重寫以處理特殊的字元鍵和實體按鍵。

4. 系統組合鍵的判定

  在使用鍵盤的時候,通常會使用到CTRL+SHIFT+ALT 類似的組合鍵功能。對于此,如何進行判定?

  通過KeyUp 事件能夠來處理(這裡說明一下為什麼不用KeyDown,因為在判定KeyDown的時候,CTRL、SHIFT和ALT 屬于一直按下狀态,然後再加另外一個鍵是不能準确捕獲組合鍵,是以使用 KeyDown 是不能準确判斷出的,要通過KeyUp 事件來判定)。

5. 捕獲PrScrn按鍵事件

  通過一種鈎子的方式可以判定PrScrn 按鍵事件,鈎子可以擷取任何鍵盤事件。

6.KeyPress 和KeyDown 、KeyUp之間的差別

  1. KeyPress主要用來捕獲數字(注意:包括Shift+數字的符号)、字母(注意:包括大小寫)、小鍵盤等除了F1-12、SHIFT、Alt、Ctrl、Insert、Home、PgUp、Delete、End、PgDn、ScrollLock、Pause、NumLock、{菜單鍵}、{開始鍵}和方向鍵外的ANSI字元
  2. KeyDown 和KeyUp 通常可以捕獲鍵盤除了PrScrn所有按鍵(這裡不讨論特殊鍵盤的特殊鍵)
  3. KeyPress 隻能捕獲單個字元
  4. KeyDown 和KeyUp 可以捕獲組合鍵。
  5. KeyPress 可以捕獲單個字元的大小寫
  6. KeyDown和KeyUp 對于單個字元捕獲的KeyValue 都是一個值,也就是不能判斷單個字元的大小寫。
  7. KeyPress 不區分小鍵盤和主鍵盤的數字字元。
  8. KeyDown 和KeyUp 區分小鍵盤和主鍵盤的數字字元。
  9. 其中PrScrn 按鍵KeyPress、KeyDown和KeyUp 都不能捕獲。

  抄抄了那麼多,感覺有點過于理論化,其實我們在按下一個鍵時,KeyDown和KeyPress兩個都要發生(一個在前,一個在後),雖然兩個看上去沒什麼差別,但是兩者還是有本質的差別。而 keyup 則是我們将按鍵擡起時觸發的,屬于整個按鍵過程的最後階段,是以有其特定的用處,最典型的就是左右資料預覽,以及擷取最後一個點選字元。

下面是測試代碼和注釋:(結果就隻能自己打開去看了)

<!DOCTYPE html>
<html >
<head>
    <meta charset="UTF-8">
    <title>keydown、keypress、keyup的差別</title>
    <style>
        .area{
            float: left;
            display: inline;
            width: 50%
        }
    </style>
</head>
<body>
<div>
    <!--keydown、keypress、keyup觸發的先後順序-->
    <span>随意輸入一些字元:</span> <input class="keydown-keyup" style="background-color:#00FFFF" type="text"/>
    <p>當 keydown、keypress 和 keyup 事件相繼觸發時,輸入區域會改變顔色。進而可以看出三個事件觸發的先後順序</p>
    <p>在 keypress 一直按着不放開,keyup事件不會觸發,但該按鍵狀态碼會一直被擷取,文本框資料會一直添加</p>
</div>

<div style="margin-top: 100px">
    <div style="width: 100%">
        <textarea id="t1" class="area"></textarea>
        <div id="v1" class="area"></div>
    </div>
    <!--按鍵按下觸發keydown事件,t1顯示目前按鍵字元,v1始終能擷取到新輸入的字元資料。按鍵不放開目前字元會一直往後添加,同樣v1的資料也會一直往後添加-->

    <div style="width: 100%">
        <textarea id="t2" class="area"></textarea>
        <div id="v2" class="area"></div>
    </div>
    <!--按鍵按下觸發keypress事件,t2顯示目前按鍵字元,v2始終能擷取到新輸入的字元資料。按鍵不放開目前字元會一直往後添加,同樣v2的資料也會一直往後添加-->

    <div style="width: 100%">
        <textarea id="t3" class="area"></textarea>
        <div id="v3" class="area"></div>
    </div>
    <!--按鍵按下觸發keyup事件,t2顯示目前按鍵字元,按鍵不放開則目前字元會一直往後添加,但v2并不能擷取到新輸入的字元資料-->
    <div style="clear: both"></div>

    <!--這裡分别給三個textarea标簽綁定三種事件,其中t1,t2均不能實時将資料同步到v1,v2中(總是缺少目前正在輸入的字元),keydown、keypress因為是按下按鍵就觸發,是以按下按鍵時目前輸入字元并未傳回,因而不能實時同步。
    而keyup則不一樣,keyup必須等到按鍵松開才能觸發,才能将資料同步,當然如果我一直按着按鍵(一直處于keydown、keypress階段),雖然textarea資料一直在往後添加,但是下面div的資料卻無法同步,必須要按鍵松開才能同步。
    這樣就說明了這三種事件觸發之間的差別,keydown是在按下時觸發,雖然傳回鍵盤的代碼,但還沒得到最後的輸入結果;keypress也是一樣,雖然得到了ASCII字元,但還沒得到需要的字元;keyup才能得到最後的完整資料。
    因而keyup适用于文本框的資料輸入和同步,keydown 與 keypress更适用于通過鍵盤控制頁面功能的實作(如回車事件)。是以可以根據不同的需求,适當的選擇!-->

</div>

<div style="margin-top: 100px">
    <!--在看了三者之間的細小差别後,再來看下keydown、keypress之間的差別-->
    <div>
        <span>随意輸入一些字元:</span><input class="keydown" type="text"/>
        <p>這裡顯示keydown事件傳回的資料:</p><span id="keydown"></span>
    </div>
    <div>
        <span>随意輸入一些字元:</span><input class="keypress" type="text"/>
        <p>這裡顯示keypress事件傳回的資料:</p><span id="keypress"></span>
    </div>
</div>

<script type="text/javascript" src="./framework/jquery-1.8.0.min.js"></script>
<script type="text/javascript">
    $(document).ready(function () {
        $(".keydown-keyup").keydown(function () {
            console.log("keydown正在執行!");
            $(".keydown-keyup").css("background-color", "#FF0000");
        });
        $(".keydown-keyup").keypress(function () {
            console.log("keypress正在執行!");
            $(".keydown-keyup").css("background-color", "#FFA500");
        });
        $(".keydown-keyup").keyup(function () {
            console.log("keyup正在執行!");
            $(".keydown-keyup").css("background-color", "#4B0082");
        });

        $('#t1').on('keydown', function () {
            $('#v1').text($(this).val());
        });
        $('#t2').on('keypress', function () {
            $('#v2').text($(this).val());
        });
        $('#t3').on('keyup', function () {
            $('#v3').text($(this).val());
        });


        $(".keydown").keydown(function (event) {
            console.log(event);
            var key =  window.event ? window.event.keyCode : event.which;
            if (window.event) { //ie
                $("#keydown").html("Key: " + key);
                window.event.returnValue = false;
            } else {    //非IE
                $("#keydown").html("Key: " + key);
                return false;
            }
        });
        $(".keypress").keypress(function (event) {
            console.log(event);
            var key =  window.event ? window.event.keyCode : event.which;
            if (window.event) { //ie
                $("#keypress").html("Key: " + key);
                window.event.returnValue = false;
            } else {    //非IE
                $("#keypress").html("Key: " + key);
                return false;
            }
        });
        /**通過對event事件對象的對比,發現keydown和keypress兩個事件傳回的事件對象基本相同,但有一個很細微的卻很重要的差別:charCode值不一樣
         * keydown 事件對象的charCode值始終為:0
         * keypress 事件對象的charCode值卻跟keyCode值一樣(目前按鍵字元的ASCII字元)。
         * 是以:charCode 傳回的是 onkeypress 事件觸發鍵值的字元代碼(ASCII字元代碼,就是ASCII碼,一一對應)。而 keyCode 傳回的是 onkeydown onkeypress 以及 onkeyup 事件的鍵的代碼(還是ASCII碼)。
         * 整個系統都是采用ASCII碼表(ASCII字元和ASCII碼一一對應,比如鍵盤"p"鍵,對應ASCII字元碼:"p",對應ASCII碼:112)
         */
    });
</script>
</body>
</html>
           

  兜了一個大圈,終于對這三者之間的差別有了一定的了解。

  總結:keyup适用于文本框的資料輸入和同步,以及資料的擷取;keydown 與 keypress更适用于通過鍵盤控制頁面功能的實作(如回車事件)。