JAVASCRIPT事件模型及事件代理

事件簡介

事件的三要素

事件的三要素:事件源、事件、事件驅(qū)動(dòng)程序。

  • 事件源:引發(fā)后續(xù)事件的html標(biāo)簽。
  • 事件:js已經(jīng)定義好了(見下圖)。
  • 事件驅(qū)動(dòng)程序:對(duì)樣式和html的操作。也就是DOM。

也就是說,我們可以在時(shí)間對(duì)應(yīng)的屬性中寫一些js代碼,當(dāng)事件被觸發(fā)時(shí),這些代碼將會(huì)執(zhí)行。

代碼書寫步驟如下:(重要)

  • (1)獲取事件源:document.getElementById(“box”); // 類似于Android里面的findViewById
  • (2)綁定事件: 事件源box.事件onclick = function(){ 事件驅(qū)動(dòng)程序 };
  • (3)書寫事件驅(qū)動(dòng)程序:關(guān)于DOM的操作。

最簡單的代碼舉例:(點(diǎn)擊box1,然后彈框)

<body>
<div id="box1"></div>

<script type="text/javascript">
    // 1、獲取事件源
    var div = document.getElementById("box1");
    // 2、綁定事件
    div.onclick = function () {
        // 3、書寫事件驅(qū)動(dòng)程序
        alert("我是彈出的內(nèi)容");
    }
</script>

</body>

常見的事件如下:


下面針對(duì)這事件的三要素,進(jìn)行分別介紹。

1、獲取事件源的方式(DOM節(jié)點(diǎn)的獲?。?/h3>

獲取事件源的常見方式如下:

var div1 = document.getElementById("box1");      //方式一:通過id獲取單個(gè)標(biāo)簽

var arr1 = document.getElementsByTagName("div");     //方式二:通過 標(biāo)簽名 獲得 標(biāo)簽數(shù)組,所以有s

var arr2 = document.getElementsByClassName("hehe");  //方式三:通過 類名 獲得 標(biāo)簽數(shù)組,所以有s

2、綁定事件的方式

方式一:直接綁定匿名函數(shù)

<div id="box1" ></div>

<script type="text/javascript">
    var div1 = document.getElementById("box1");
    //綁定事件的第一種方式
    div1.onclick = function () {
        alert("我是彈出的內(nèi)容");
    }
</script>

方式二:先單獨(dú)定義函數(shù),再綁定

 <div id="box1" ></div>

<script type="text/javascript">
    var div1 = document.getElementById("box1");
    //綁定事件的第二種方式
    div1.onclick = fn;   //注意,這里是fn,不是fn()。fn()指的是返回值。
    //單獨(dú)定義函數(shù)
    function fn() {
        alert("我是彈出的內(nèi)容");
    }
</script>

注意上方代碼的注釋。綁定的時(shí)候,是寫fn,不是寫fn()。fn代表的是整個(gè)函數(shù),而fn()代表的是返回值。

方式三:行內(nèi)綁定

<!--行內(nèi)綁定-->
<div id="box1" onclick="fn()"></div>

<script type="text/javascript">

    function fn() {
        alert("我是彈出的內(nèi)容");
    }

</script>

注意第一行代碼,綁定時(shí),是寫的"fn()",不是寫的"fn"。因?yàn)榻壎ǖ倪@段代碼不是寫在js代碼里的,而是被識(shí)別成了字符串。

3、事件驅(qū)動(dòng)程序

我們在上面是拿alert舉例,不僅如此,我們還可以操作標(biāo)簽的屬性和樣式。舉例如下:

點(diǎn)擊鼠標(biāo)時(shí),原本粉色的div變大了,背景變紅:

    <style>
        #box1 {
            width: 100px;
            height: 100px;
            background-color: pink;
            cursor: pointer;
        }
    </style>
</head>

<body>

<div id="box1" ></div>

<script type="text/javascript">
    var div1 = document.getElementById("box1");
    //點(diǎn)擊鼠標(biāo)時(shí),原本粉色的div變大了,背景變紅了
    div1.onclick = function () {
        div1.style.width = "200px";   //屬性值要寫引號(hào)
        div1.style.height = "200px";
        div1.style.backgroundColor = "red";   //屬性名是backgroundColor,不是background-color
    }
</script>

上方代碼的注意事項(xiàng):

  • 在js里寫屬性值時(shí),要用引號(hào)
  • 在js里寫屬性名時(shí),是backgroundColor,不是CSS里面的background-color

綁定事件的兩種方式/DOM事件的級(jí)別

DOM0的寫法:onclick

    element.onclick = function () {

    }

舉例:

<body>
<button>點(diǎn)我</button>
<script>
    var btn = document.getElementsByTagName("button")[0];

    //這種事件綁定的方式,如果綁定多個(gè),則后面的會(huì)覆蓋掉前面的
    btn.onclick = function () {
        console.log("事件1");
    }

    btn.onclick = function () {
        console.log("事件2");
    }

</script>
</body>

點(diǎn)擊按鈕后,上方代碼的打印結(jié)果:

事件2

我們可以看到,DOM對(duì)象.事件 = 函數(shù)的這種綁定事件的方式:一個(gè)元素的一個(gè)事件只能綁定一個(gè)響應(yīng)函數(shù)。如果綁定了多個(gè)響應(yīng)函數(shù),則后者會(huì)覆蓋前者。

DOM2的寫法:addEventListener(高版本瀏覽器)

    element.addEventListener('click', function () {

    }, false);

參數(shù)解釋:

  • 參數(shù)1:事件名的字符串(注意,沒有on)
  • 參數(shù)2:回調(diào)函數(shù):當(dāng)事件觸發(fā)時(shí),該函數(shù)會(huì)被執(zhí)行
  • 參數(shù)3:true表示捕獲階段觸發(fā),false表示冒泡階段觸發(fā)(默認(rèn))。如果不寫,則默認(rèn)為false。【重要】

舉例:

<body>
<button>按鈕</button>
<script>
    var btn = document.getElementsByTagName("button")[0];

    // addEventListener: 事件監(jiān)聽器。 原事件被執(zhí)行的時(shí)候,后面綁定的事件照樣被執(zhí)行
    // 這種寫法不存在響應(yīng)函數(shù)被覆蓋的情況。(更適合團(tuán)隊(duì)開發(fā))
    btn.addEventListener("click", fn1);
    btn.addEventListener("click", fn2);

    function fn1() {
        console.log("事件1");
    }

    function fn2() {
        console.log("事件2");
    }

</script>
</body>

點(diǎn)擊按鈕后,上方代碼的打印結(jié)果:

    事件1
    事件2

我們可以看到,addEventListener()這種綁定事件的方式:

  • 一個(gè)元素的一個(gè)事件,可以綁定多個(gè)響應(yīng)函數(shù)。不存在響應(yīng)函數(shù)被覆蓋的情況。執(zhí)行順序是:事件被觸發(fā)時(shí),響應(yīng)函數(shù)會(huì)按照函數(shù)的綁定順序執(zhí)行。
  • addEventListener()中的this,是綁定事件的對(duì)象。
  • addEventListener()不支持 IE8 及以下的瀏覽器。在IE8中可以使用attachEvent來綁定事件(詳見下一小段)。

DOM2的寫法:attachEvent(IE8及以下版本瀏覽器)

    element.attachEvent('onclick', function () {

    });

參數(shù)解釋:

  • 參數(shù)1:事件名的字符串(注意,有on)
  • 參數(shù)2:回調(diào)函數(shù):當(dāng)事件觸發(fā)時(shí),該函數(shù)會(huì)被執(zhí)行

舉例:

    <body>
        <button>按鈕</button>
        <script>
            var btn = document.getElementsByTagName('button')[0];

            btn.attachEvent('onclick', function() {
                console.log('事件1');
            });

            btn.attachEvent('onclick', function() {
                console.log('事件2');
            });
        </script>
    </body>

在低版本的IE瀏覽器上,點(diǎn)擊按鈕后,上方代碼的打印結(jié)果:

    事件2
    事件1

我們可以看到,attachEvent()這種綁定事件的方式:

  • 一個(gè)元素的一個(gè)事件,可以綁定多個(gè)響應(yīng)函數(shù)。不存在響應(yīng)函數(shù)被覆蓋的情況。注意:執(zhí)行順序是,后綁定的先執(zhí)行。
  • attachEvent()中的this,是window

兼容性寫法

上面的內(nèi)容里,需要強(qiáng)調(diào)的是:

  • addEventListener()中的this,是綁定事件的對(duì)象。
  • attachEvent()中的this,是window。

既然這兩個(gè)寫法的this不同,那么,有沒有一種兼容性的寫法可以確保這兩種綁定方式的this是相同的呢?我們可以封裝一下。代碼如下:

    <body>
        <button>按鈕</button>
        <script>
            var btn = document.getElementsByTagName('button')[0];

            myBind(btn , "click" , function(){
                alert(this);
            });



            //定義一個(gè)函數(shù),用來為指定元素綁定響應(yīng)函數(shù)
            /*
             * addEventListener()中的this,是綁定事件的對(duì)象
             * attachEvent()中的this,是window
             *  需要統(tǒng)一兩個(gè)方法this
             */
            /*
             * 參數(shù):
             *  element 要綁定事件的對(duì)象
             *  eventStr 事件的字符串(不要on)
             *  callback 回調(diào)函數(shù)
             */
            function myBind(element , eventStr , callback){
                if(element.addEventListener){
                    //大部分瀏覽器兼容的方式
                    element.addEventListener(eventStr , callback , false);
                }else{
                    /*
                     * this是誰,由調(diào)用方式?jīng)Q定
                     * callback.call(element)
                     */
                    //IE8及以下
                    element.attachEvent("on"+eventStr , function(){
                        //在匿名函數(shù) function 中調(diào)用回調(diào)函數(shù)callback
                        callback.call(element);
                    });
                }
            }

        </script>
    </body>

事件對(duì)象

當(dāng)事件的響應(yīng)函數(shù)被觸發(fā)時(shí),會(huì)產(chǎn)生一個(gè)事件對(duì)象event。瀏覽器每次都會(huì)將這個(gè)事件event作為實(shí)參傳進(jìn)之前的響應(yīng)函數(shù)。

這個(gè)對(duì)象中包含了與當(dāng)前事件相關(guān)的一切信息。比如鼠標(biāo)的坐標(biāo)、鍵盤的哪個(gè)按鍵被按下、鼠標(biāo)滾輪滾動(dòng)的方向等。

獲取 event 對(duì)象(兼容性問題)

所有瀏覽器都支持event對(duì)象,但支持的方式不同。如下。

(1)普通瀏覽器的寫法是 event。比如:

(2)ie 678 的寫法是 window.event。此時(shí),事件對(duì)象 event 是作為window對(duì)象的屬性保存的。

于是,我們可以采取一種兼容性的寫法。如下:

    event = event || window.event; // 兼容性寫法

代碼舉例:

<!DOCTYPE html>
<html>
<head lang="en">
    <meta charset="UTF-8">
    <title></title>
</head>
<body>
<script>
    //點(diǎn)擊頁面的任何部分
    document.onclick = function (event) {
        event = event || window.event; ////兼容性寫法

        console.log(event);
        console.log(event.timeStamp);
        console.log(event.bubbles);
        console.log(event.button);
        console.log(event.pageX);
        console.log(event.pageY);
        console.log(event.screenX);
        console.log(event.screenY);
        console.log(event.target);
        console.log(event.type);
        console.log(event.clientX);
        console.log(event.clientY);
    }
</script>
</body>
</html>

event 屬性

event 有很多屬性,比如:

由于pageX 和 pageY的兼容性不好,我們可以這樣做:

  • 鼠標(biāo)在頁面的位置 = 滾動(dòng)條滾動(dòng)的距離 + 可視區(qū)域的坐標(biāo)。

使 div 跟隨鼠標(biāo)移動(dòng)

代碼實(shí)現(xiàn):

<!DOCTYPE html>
<html>
  <head>
    <meta charset="UTF-8" />
    <title></title>
    <style type="text/css">
      #box1 {
        width: 100px;
        height: 100px;
        background-color: red;
        /*
        * 開啟box1的絕對(duì)定位
        */
        position: absolute;
      }
    </style>

    <script type="text/javascript">
      window.onload = function() {
        /*
         * 使div可以跟隨鼠標(biāo)移動(dòng)
         */

        //獲取box1
        var box1 = document.getElementById("box1");

        //給整個(gè)頁面綁定:鼠標(biāo)移動(dòng)事件
        document.onmousemove = function(event) {
          //兼容的方式獲取event對(duì)象
          event = event || window.event;

          // 鼠標(biāo)在頁面的位置 = 滾動(dòng)條滾動(dòng)的距離 + 可視區(qū)域的坐標(biāo)。
          var pagex = event.pageX || scroll().left + event.clientX;
          var pagey = event.pageY || scroll().top + event.clientY;

          //   設(shè)置div的偏移量(相對(duì)于整個(gè)頁面)
          // 注意,如果想通過 style.left 來設(shè)置屬性,一定要給 box1開啟絕對(duì)定位。
          box1.style.left = pagex + "px";
          box1.style.top = pagey + "px";
        };
      };

      // scroll 函數(shù)封裝
      function scroll() {
        return {
          //此函數(shù)的返回值是對(duì)象
          left: window.pageYOffset || document.body.scrollTop || document.documentElement.scrollTop,
          right:
            window.pageXOffset || document.body.scrollLeft || document.documentElement.scrollLeft
        };
      }
    </script>
  </head>
  <body style="height: 1000px;width: 2000px;">
    <div id="box1"></div>
  </body>
</html>

event.target 獲取的是觸發(fā)事件的標(biāo)簽元素

event.currentTarget 獲取到的是發(fā)起事件的標(biāo)簽元素

DOM事件流

事件傳播的三個(gè)階段是:事件捕獲、事件冒泡和目標(biāo)。

  • 事件捕獲階段:事件從祖先元素往子元素查找(DOM樹結(jié)構(gòu)),直到捕獲到事件目標(biāo) target。在這個(gè)過程中,默認(rèn)情況下,事件相應(yīng)的監(jiān)聽函數(shù)是不會(huì)被觸發(fā)的。
  • 事件目標(biāo):當(dāng)?shù)竭_(dá)目標(biāo)元素之后,執(zhí)行目標(biāo)元素該事件相應(yīng)的處理函數(shù)。如果沒有綁定監(jiān)聽函數(shù),那就不執(zhí)行。
  • 事件冒泡階段:事件從事件目標(biāo) target 開始,從子元素往冒泡祖先元素冒泡,直到頁面的最上一級(jí)標(biāo)簽。

如下圖所示:

Snipaste_2020-04-21_12-50-18.png

PS:這個(gè)概念類似于 Android 里的 touch 事件傳遞

事件捕獲

addEventListener可以捕獲事件:

    box1.addEventListener("click", function () {
        alert("捕獲 box3");
    }, true);

上面的方法中,參數(shù)為true,代表事件在捕獲階段執(zhí)行。

重點(diǎn):捕獲階段,事件依次傳遞的順序是:window --> document --> html--> body --> 父元素、子元素、目標(biāo)元素。

這幾個(gè)元素在事件捕獲階段的完整寫法是:

    window.addEventListener("click", function () {
        alert("捕獲 window");
    }, true);

    document.addEventListener("click", function () {
        alert("捕獲 document");
    }, true);

    document.documentElement.addEventListener("click", function () {
        alert("捕獲 html");
    }, true);

    document.body.addEventListener("click", function () {
        alert("捕獲 body");
    }, true);

    fatherBox.addEventListener("click", function () {
        alert("捕獲 father");
    }, true);

    childBox.addEventListener("click", function () {
        alert("捕獲 child");
    }, true);

說明:

(1)第一個(gè)接收到事件的對(duì)象是 window(有人會(huì)說body,有人會(huì)說html,這都是錯(cuò)誤的)。

(2)JS中涉及到DOM對(duì)象時(shí),有兩個(gè)對(duì)象最常用:window、doucument。它們倆是最先獲取到事件的。

補(bǔ)充一個(gè)知識(shí)點(diǎn):

在 js中:

  • 如果想獲取 html節(jié)點(diǎn),方法是document.documentElement
  • 如果想獲取 body 節(jié)點(diǎn),方法是:document.body。

二者不要混淆了。

事件冒泡

事件冒泡: 當(dāng)一個(gè)元素上的事件被觸發(fā)的時(shí)候(比如說鼠標(biāo)點(diǎn)擊了一個(gè)按鈕),同樣的事件將會(huì)在那個(gè)元素的所有祖先元素中被觸發(fā)。這一過程被稱為事件冒泡;這個(gè)事件從原始元素開始一直冒泡到DOM樹的最上層。

通俗來講,冒泡指的是:子元素的事件被觸發(fā)時(shí),父元素的同樣的事件也會(huì)被觸發(fā)。取消冒泡就是取消這種機(jī)制。

冒泡順序

一般的瀏覽器: (除IE6.0之外的瀏覽器)

  • div -> body -> html -> document -> window

IE6.0:

  • div -> body -> html -> document

不是所有的事件都能冒泡

以下事件不冒泡:blur、focus、load、unload、onmouseenter、onmouseleave。意思是,事件不會(huì)往父元素那里傳遞。

我們檢查一個(gè)元素是否會(huì)冒泡,可以通過事件的以下參數(shù):

    event.bubbles

如果返回值為true,說明該事件會(huì)冒泡;反之則相反。

舉例:

    box1.onclick = function (event) {
        alert("冒泡 child");

        event = event || window.event;
        console.log(event.bubbles); //打印結(jié)果:true。說明 onclick 事件是可以冒泡的
    }

阻止冒泡

大部分情況下,冒泡都是有益的。當(dāng)然,如果你想阻止冒泡,也是可以的??梢园聪旅娴姆椒ㄗ柚姑芭?。

阻止冒泡的方法

w3c的方法:(火狐、谷歌、IE11)

    event.stopPropagation();

IE10以下則是:

event.cancelBubble = true

兼容代碼如下:

   box3.onclick = function (event) {

        alert("child");

        //阻止冒泡
        event = event || window.event;

        if (event && event.stopPropagation) {
            event.stopPropagation();
        } else {
            event.cancelBubble = true;
        }
    }

上方代碼中,我們對(duì)box3進(jìn)行了阻止冒泡,產(chǎn)生的效果是:事件不會(huì)繼續(xù)傳遞到 father、grandfather、body了。

事件委托

事件委托,通俗地來講,就是把一個(gè)元素響應(yīng)事件(click、keydown......)的函數(shù)委托到另一個(gè)元素。

比如說有一個(gè)列表 ul,列表之中有大量的列表項(xiàng) <a>標(biāo)簽:

<ul id="parent-list">
    <li><a href="javascript:;" class="my_link">超鏈接一</a></li>
    <li><a href="javascript:;" class="my_link">超鏈接二</a></li>
    <li><a href="javascript:;" class="my_link">超鏈接三</a></li>
</ul>

當(dāng)我們的鼠標(biāo)移到<a>標(biāo)簽上的時(shí)候,需要獲取此<a>的相關(guān)信息并飄出懸浮窗以顯示詳細(xì)信息,或者當(dāng)某個(gè)<a>被點(diǎn)擊的時(shí)候需要觸發(fā)相應(yīng)的處理事件。我們通常的寫法,是為每個(gè)<a>都綁定類似onMouseOver或者onClick之類的事件監(jiān)聽:

    window.onload = function(){
        var parentNode = document.getElementById("parent-list");
        var aNodes = parentNode.getElementByTagName("a");
        for(var i=0, l = aNodes.length; i < l; i++){

            aNodes[i].onclick = function() {
                console.log('我是超鏈接 a 的單擊相應(yīng)函數(shù)');
            }
        }
    }

但是,上面的做法過于消耗內(nèi)存和性能。我們希望,只綁定一次事件,即可應(yīng)用到多個(gè)元素上,即使元素是后來添加的。

因此,比較好的方法就是把這個(gè)點(diǎn)擊事件綁定到他的父層,也就是 ul 上,然后在執(zhí)行事件函數(shù)的時(shí)候再去匹配判斷目標(biāo)元素。如下:

    <!DOCTYPE html>
<html>
    <head>
        <meta charset="utf-8" />
        <title></title>
        <script type="text/javascript">
            window.onload = function() {

                // 獲取父節(jié)點(diǎn),并為它綁定click單擊事件。 false 表示事件在冒泡階段觸發(fā)(默認(rèn))
                document.getElementById('parent-list').addEventListener('click', function(event) {
                    event = event || window.event;

                    // e.target 表示:觸發(fā)事件的對(duì)象
                    //如果觸發(fā)事件的對(duì)象是我們期望的元素,則執(zhí)行否則不執(zhí)行
                    if (event.target && event.target.className == 'link') {
                    // 或者寫成 if (event.target && event.target.nodeName.toUpperCase() == 'A') {
                        console.log('我是ul的單擊響應(yīng)函數(shù)');
                    }
                }, false);
            };
        </script>
    </head>
    <body>
        <ul id="parent-list" style="background-color: #bfa;">
            <li>
                <p>我是p元素</p>
            </li>
            <li><a href="javascript:;" class="link">超鏈接一</a></li>
            <li><a href="javascript:;" class="link">超鏈接二</a></li>
            <li><a href="javascript:;" class="link">超鏈接三</a></li>
        </ul>
    </body>

上方代碼,為父節(jié)點(diǎn)注冊 click 事件,當(dāng)子節(jié)點(diǎn)被點(diǎn)擊的時(shí)候,click事件會(huì)從子節(jié)點(diǎn)開始向父節(jié)點(diǎn)冒泡。父節(jié)點(diǎn)捕獲到事件之后,開始執(zhí)行方法體里的內(nèi)容:通過判斷 event.target 拿到了被點(diǎn)擊的子節(jié)點(diǎn)<a>。從而可以獲取到相應(yīng)的信息,并作處理。

換而言之,參數(shù)為false,說明事件是在冒泡階段觸發(fā)(子元素向父元素傳遞事件)。而父節(jié)點(diǎn)注冊了事件函數(shù),子節(jié)點(diǎn)沒有注冊事件函數(shù),此時(shí),會(huì)在父節(jié)點(diǎn)中執(zhí)行函數(shù)體里的代碼。

總結(jié):事件委托是利用了冒泡機(jī)制,減少了事件綁定的次數(shù),減少內(nèi)存消耗,提高性能。

鼠標(biāo)的拖拽事件

拖拽的流程:

(1)onmousedown:當(dāng)鼠標(biāo)在被拖拽元素上按下時(shí),開始拖拽;

(2)onmousemove:當(dāng)鼠標(biāo)移動(dòng)時(shí)被拖拽元素跟隨鼠標(biāo)移動(dòng);

(3)onmouseup:當(dāng)鼠標(biāo)松開時(shí),被拖拽元素固定在當(dāng)前位置。

鼠標(biāo)的滾輪事件

onmousewheel:鼠標(biāo)滾輪滾動(dòng)的事件,會(huì)在滾輪滾動(dòng)時(shí)觸發(fā)。但是火狐不支持該屬性。

DOMMouseScroll:在火狐中需要使用 DOMMouseScroll 來綁定滾動(dòng)事件。注意該事件需要通過addEventListener()函數(shù)來綁定。

鍵盤事件

事件名

onkeydown:按鍵被按下。

onkeyup:按鍵被松開。

注意

  • 如果一直按著某一個(gè)按鍵不松手,那么,onkeydown事件會(huì)一直觸發(fā)。此時(shí),松開鍵盤,onkeyup事件會(huì)執(zhí)行一次。
  • 當(dāng)onkeydown連續(xù)觸發(fā)時(shí),第一次和第二次之間會(huì)間隔稍微長一點(diǎn),后續(xù)的間隔會(huì)非常快。這種設(shè)計(jì)是為了防止誤操作的發(fā)生。

鍵盤事件一般都會(huì)綁定給一些可以獲取到焦點(diǎn)的對(duì)象或者是document。代碼舉例:

    <body>
        <script>
            document.onkeydown = function(event) {
                event = event || window.event;
                console.log('qianguyihao 鍵盤按下了');
            };

            document.onkeyup = function() {
                console.log('qianguyihao 鍵盤松開了');
            };
        </script>

        <input type="text" />
    </body>

判斷哪個(gè)鍵盤被按下

可以通過event事件對(duì)象的keyCode來獲取按鍵的編碼。

此外,event事件對(duì)象里面還提供了以下幾個(gè)屬性:

  • altKey
  • ctrlKey
  • shiftKey

上面這三個(gè)屬性,可以用來判斷alt、ctrl、和shift是否被按下。如果按下則返回true,否則返回false。代碼舉例:

    <body>
        <script>
            document.onkeydown = function(event) {
                event = event || window.event;
                console.log('qianguyihao:鍵盤按下了');

                // 判斷y和ctrl是否同時(shí)被按下
                if (event.ctrlKey && event.keyCode === 89) {
                    console.log('ctrl和y都被按下了');
                }
            };
        </script>
    </body>

舉例:input 文本框中,禁止輸入數(shù)字。代碼實(shí)現(xiàn):

    <body>
        <input type="text" />

        <script>
            //獲取input
            var input = document.getElementsByTagName('input')[0];

            input.onkeydown = function(event) {
                event = event || window.event;

                //console.log('qianguyihao:' + event.keyCode);
                //數(shù)字 48 - 57
                //使文本框中不能輸入數(shù)字
                if (event.keyCode >= 48 && event.keyCode <= 57) {
                    //在文本框中輸入內(nèi)容,屬于onkeydown的默認(rèn)行為
                    return false; // 如果在onkeydown中取消了默認(rèn)行為,則輸入的內(nèi)容,不會(huì)出現(xiàn)在文本框中
                }
            };
        </script>
    </body>

舉例:通過鍵盤的方向鍵,移動(dòng)盒子

代碼實(shí)現(xiàn):

<!DOCTYPE html>
<html>
    <head>
        <meta charset="UTF-8" />
        <title></title>
        <style type="text/css">
            #box1 {
                width: 100px;
                height: 100px;
                background-color: red;
                position: absolute;
            }
        </style>
    </head>
    <body>
        <div id="box1"></div>

        <script type="text/javascript">
            // 使div可以根據(jù)不同的方向鍵向不同的方向移動(dòng)
            /*
             * 按左鍵,div向左移
             * 按右鍵,div向右移
             * ...
             */

            //為document綁定一個(gè)按鍵按下的事件
            document.onkeydown = function(event) {
                event = event || window.event;

                //定義一個(gè)變量,來表示移動(dòng)的速度
                var speed = 10;

                //當(dāng)用戶按了ctrl以后,速度加快
                if (event.ctrlKey) {
                    console.log('smyhvae ctrl');
                    speed = 20;
                }

                /*
                 * 37 左
                 * 38 上
                 * 39 右
                 * 40 下
                 */
                switch (event.keyCode) {
                    case 37:
                        //alert("向左"); left值減小
                        box1.style.left = box1.offsetLeft - speed + 'px'; // 在初始值的基礎(chǔ)之上,減去 speed 大小
                        break;
                    case 39:
                        //alert("向右");
                        box1.style.left = box1.offsetLeft + speed + 'px';
                        break;
                    case 38:
                        //alert("向上");
                        box1.style.top = box1.offsetTop - speed + 'px';
                        break;
                    case 40:
                        //alert("向下");
                        box1.style.top = box1.offsetTop + speed + 'px';
                        break;
                }
            };
        </script>
    </body>
</html>


上方代碼,待改進(jìn)的地方:

(1)移動(dòng)盒子時(shí),如果要加速,需要先按方向鍵,再按Ctrl鍵。

(2)首次移動(dòng)盒子時(shí),動(dòng)作較慢。后續(xù)如果學(xué)習(xí)了定時(shí)器相關(guān)的內(nèi)容,可以再改進(jìn)。

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡書系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。

推薦閱讀更多精彩內(nèi)容

  • 本篇博客源地址 總結(jié): 鼠標(biāo)事件 1.click與dbclick事件ele.click()ele.click(ha...
    ZombieBrandg閱讀 682評(píng)論 0 1
  • 總結(jié): 鼠標(biāo)事件 1.click與dbclick事件$ele.click()$ele.click(handler(...
    阿r阿r閱讀 1,628評(píng)論 2 10
  • 事件是一種異步編程的實(shí)現(xiàn)方式,本質(zhì)上是程序各個(gè)組成部分之間的通信。DOM支持大量的事件,本節(jié)介紹DOM的事件編程。...
    許先生__閱讀 954評(píng)論 0 3
  • (續(xù)jQuery基礎(chǔ)(1)) 第5章 DOM節(jié)點(diǎn)的復(fù)制與替換 (1)DOM拷貝clone() 克隆節(jié)點(diǎn)是DOM的常...
    凜0_0閱讀 1,359評(píng)論 0 8
  • 以下文章為轉(zhuǎn)載,對(duì)理解JavaScript中的事件處理機(jī)制很有幫助,淺顯易懂,特分享于此。 什么是事件? 事件(E...
    jxyjxy閱讀 3,060評(píng)論 1 10