Web APIs 学习笔记(四)--- 事件进阶

一、绑定事件

​ 给元素添加事件又称为注册事件或者绑定事件。

1、传统方式

​ 通过 元素.事件 = function(){} 的形式来绑定事件,绑定的事件都是以 on 开头的事件,比如onclick、onmouseover 等,但是有一个很重要的缺陷:元素的注册事件具有唯一性,也就是说同一个元素的同一个事件只能有一个处理函数,后面绑定的处理函数会覆盖掉前面注册的处理函数。

2、监听注册方式

​ 通过 元素.addEventListener() 来绑定事件,是 W3C 组织推荐使用的方式,绑定的事件不需要以on开头,而且它解决了传统方式的缺陷:能够为同一个元素的同一个事件绑定多个事件,并在触发时按照绑定的顺序依次执行

元素.addEventListener(type,listener[,useCapture]):该方法有三个参数,第一个参数type(必写) 是代表事件类型的字符串 ,比如 ‘click’、‘mouseover’ 等,此时不需要带 on 。第二个参数listener(必写) 是代表事件处理函数,当type事件触发时,就会执行该函数。第三个参数useCapture(非必写) 是代表冒泡阶段或捕获阶段执行的,下面学习DOM事件流时再深入学习,数据类型是一个布尔值,默认值为false。

// 案例代码

<button>传统注册事件</button>
<button>方法监听注册事件</button>
<script>
    var btns = document.querySelectorAll('button');
    // 1. 传统方式注册事件
    btns[0].onclick = function() {
        alert('hi');
    }
    btns[0].onclick = function() {
            alert('hao a u');
        }
   // 2. 事件侦听注册事件 addEventListener 
   // (1) 里面的事件类型是字符串 必定加引号 而且不带on
   // (2) 同一个元素 同一个事件可以添加多个侦听器(事件处理程序)
    btns[1].addEventListener('click', function() {
        alert(22);
    })
    btns[1].addEventListener('click',fn)  
	//也可以采用这种形式 调用注册好的函数  调用时不需要加括号
	function fn(){
        alert(33);
    }
</script>

二、删除事件(解绑事件)

1、传统方式

​ 通过 元素.事件 = null 即给事件绑定一个空对象 的形式来删除事件。

2、监听注册的方式

​ 通过 元素.removeEventListener(type,listener[,useCapture]) 的形式来删除事件,共有三个参数:第一个参数type(必写) 是代表事件类型的字符串 ,比如 ‘click’、‘mouseover’ 等,此时不需要带 on 。第二个参数listener(必写) 是代表要删除的事件处理函数。第三个参数useCapture(非必写) 是代表冒泡阶段或捕获阶段,一般不会写。

// 案例代码

<div>1</div>
    <div>2</div>
    <div>3</div>
    <script>
        var divs = document.querySelectorAll('div');
        divs[0].onclick = function() {
            alert(11);
            // 1. 传统方式删除事件
            divs[0].onclick = null;
        }
        // 2. removeEventListener 删除事件
        divs[1].addEventListener('click', fn) // 里面的fn 不需要调用加小括号
        function fn() {
            alert(22);
            divs[1].removeEventListener('click', fn);
        }
    </script>

三、DOM事件流(事件冒泡和事件捕获)

​ 事件流是指从页面中接收事件的顺序,当一个事件触发时会在元素节点之间按照某种特定的顺序传播,这个传播的过程就是DOM事件流。在一个页面文档中,各级标签都是相互嵌套的,当你点击一个元素标签时,相当于你同时也点击了它的各级父元素,以至于到整个页面,比如:我们给页面中的一个div注册了单击事件,当你单击了div时,也就单击了body,单击了html,单击了document。这点击事件在各节点之间的传播过程就是DOM事件流。

​ DOM事件流会经历3个阶段:捕获阶段 ——> 目标阶段 ——> 冒泡阶段。当事件开始时,从最顶级节点开始,然后逐级向下传播到最具体元素的过程,就是捕获阶段。从最具体的元素开始,然后逐级传播到最顶级的节点的过程,就是冒泡阶段。

​ 我们可以形象的把这个过程理解为“向水里扔石头”:我们向水里面扔一块石头,首先它会有一个下降的过程,这个过程就可以理解为从最顶层向事件发生的最具体元素(目标点)的捕获过程;之后会产生泡泡,会在最低点( 最具体元素)之后漂浮到水面上,这个过程相当于事件冒泡。

Web APIs 学习笔记(四)--- 事件进阶_第1张图片

注意:①我们的JavaScript代码只能在捕获阶段和冒泡阶段的其中之一执行。②目前我们学习的方法中只有元素.addEventListener(type,listener[,useCapture]) 才能设置在捕获阶段执行,当第三个参数 useCapture 为true时,表示在捕获阶段执行,如果为false或省略 ,则表示在冒泡阶段执行。③实际开发中,我们很少时候捕获阶段,主要关注冒泡阶段。④部分事件时不存在冒泡阶段的,比如: onblur、onfocus、onmouseenter等。

// 案例代码

  <div class="father">
        <div class="son">son盒子</div>
    </div>
    <script>
        // onclick 在冒泡阶段触发
        // 冒泡阶段 如果addEventListener 第三个参数是 false 或者 省略 
        // 冒泡过程 son -> father ->body -> html -> document
        var son = document.querySelector('.son');
		// 给son注册单击事件
        son.addEventListener('click', function() {
            alert('son');
        }, false);
		// 给father注册单击事件
        var father = document.querySelector('.father');
        father.addEventListener('click', function() {
            alert('father');
        }, false);
		// 给document注册单击事件,省略第3个参数
        document.addEventListener('click', function() {
            alert('document');
        })
		// 先弹出 son 再弹出 father 最后弹出 document
		
		// 如果addEventListener() 第三个参数是 true 那么在捕获阶段触发
        // 捕获过程 document -> html -> body -> father -> son
         var son = document.querySelector('.son');
		// 给son注册单击事件,第3个参数为true
         son.addEventListener('click', function() {
             alert('son');
         }, true);
         var father = document.querySelector('.father');
		// 给father注册单击事件,第3个参数为true
         father.addEventListener('click', function() {
             alert('father');
         }, true);
		// 给document注册单击事件,第3个参数为true
        document.addEventListener('click', function() {
            alert('document');
        }, true)
		// 先弹出 document 再弹出 father 最后 son
    </script>

四、事件对象

1、事件对象的概念

​ 当事件触发后,跟这个事件相关的一系列属性方法数据的集合都会放在一个对象里面,这个对象就叫做事件对象。我们可以从事件对象中获得各种相关信息,例如谁绑定的该事件、如果是鼠标事件可以获得鼠标的信息,比如鼠标的位置、如果是键盘事件可以获得键盘的信息,比如按下的哪一个按键。

2、事件对象的使用

​ 事件被触发后就会产生事件对象,并且系统会自动将事件对象作为参数传递给事件处理函数,如果我们要使用事件对象的数据,那么我们需要在事件处理函数中声明一个形参(通常是event或者e、evt)来接受事件对象。

元素.onclick = function(event){
    这个event 就是事件对象
}
元素.addEventListener('click',function(e){
	这个e 就是事件对象
})
元素.addEventListener('click',fn)
function fn(evt) {
	这个evt 就是事件对象
}

3、事件对象的属性和方法

Web APIs 学习笔记(四)--- 事件进阶_第2张图片

​ 以上都是事件对象常用的属性和方法,其中e.srcElement 等非标准的属性方法了解即可,在实际开发中几乎不会使用。

4、e.target 和 this的区别

​ e.target 是返回触发事件的元素,this 是返回绑定事件的元素,两者在大部分时候是一致的,但是在事件冒泡时,父子元素有相同事件,单击子元素,父元素的事件处理函数也会被触发执行,这时候this指向的是父元素,因为它是绑定事件的元素对象,而target指向的是子元素,因为他是触发事件的那个具体元素对象。

// 案例代码

// 通常情况
    <div>123</div>
    <script>
        var div = document.querySelector('div');
        div.addEventListener('click', function(e) {
            // e.target 和 this指向的都是div
            console.log(e.target);
            console.log(this);

        });
    </script>

// 事件冒泡情况
  <ul>
        <li>abc</li>
        <li>abc</li>
        <li>abc</li>
    </ul>
    <script>
        var ul = document.querySelector('ul');
        ul.addEventListener('click', function(e) {
              // 我们给ul 绑定了事件  那么this 就指向ul  
              console.log(this); // ul

              // e.target 触发了事件的对象 我们点击的是li e.target 指向的就是li
              console.log(e.target); // li
        });
    </script>

5、阻止默认行为

​ 在页面文档中,有一些标签元素具有默认行为,比如a标签被单击后的默认行为是进行页面跳转,如果我们想要阻止这种默认行为,我们可以通过事件对象的 e.preventDefault() 方法 或者 return false 的方法来实现。

   <a href="http://www.baidu.com">百度</a>
    <script>
        // 阻止默认行为 让链接不跳转 
        var a = document.querySelector('a');
        a.addEventListener('click', function(e) {
             e.preventDefault(); //  dom 标准写法
        });
        // 传统的注册方式
        a.onclick = function(e) {
            // 普通浏览器 e.preventDefault();  方法
            e.preventDefault();
            // 我们可以利用return false 也能阻止默认行为 没有兼容性问题,
            // 但是在它后面的代码将不再执行,而且只适用于传统的注册方式
            return false;
        }
    </script>

6、阻止事件冒泡

​ 在很多时候,事件冒泡都会给我们带来麻烦,所以我们可以在需要的时候通过事件对象的 e.stopPropagation() 阻止事件冒泡。

// 案例代码

 <div class="father">
        <div class="son">son儿子</div>
    </div>
    <script>
        var son = document.querySelector('.son');
		// 给son注册单击事件
        son.addEventListener('click', function(e) {
            alert('son');
            e.stopPropagation(); // stop 停止  Propagation 传播
        }, false);
		// 点击son盒子 只会弹出son

        var father = document.querySelector('.father');
		// 给father注册单击事件
        father.addEventListener('click', function() {
            alert('father');
        }, false);
		// 给document注册单击事件
        document.addEventListener('click', function() {
            alert('document');
        })
		// 点击father盒子 会弹出father 和 冒泡得到的 document 
    </script>

7、鼠标事件对象

Web APIs 学习笔记(四)--- 事件进阶_第3张图片

​ 以上使我们鼠标事件对象中一些常用的属性。client 是鼠标在可视区的x和y坐标,可视区就是指你所能看到的网页的区域,不包括已经滑过去,无法看到的区域,所以坐标原点是会随着页面的滑动而变化的。page 是鼠标在页面文档的x和y坐标,也就是从页面的最开始位置的左上角为坐标原点,不会发生改变。screen 是鼠标在电脑屏幕的x和y坐标,坐标原点为电脑屏幕的左上角,不会发生改变。

// 案例代码

  <script>
        // 鼠标事件对象 MouseEvent
        document.addEventListener('click', function(e) {
            // 1. client 鼠标在可视区的x和y坐标
            console.log(e.clientX);
            console.log(e.clientY);
            console.log('---------------------');

            // 2. page 鼠标在页面文档的x和y坐标
            console.log(e.pageX);
            console.log(e.pageY);
            console.log('---------------------');

            // 3. screen 鼠标在电脑屏幕的x和y坐标
            console.log(e.screenX);
            console.log(e.screenY);

        })
    </script>

五、事件委托

​ 事件委托也称为事件代理,在jQuery中称为事件委派。当我们需要给某个父元素的所有子元素绑定相同事件时,我们可以给子元素一各个的绑定事件,但是这种方法很麻烦,代码量太大,我们还有另一种方法,就是给父元素绑定这个事件,利用冒泡原理,当子元素触发事件时,会冒泡到父元素,然后去执行事件处理代码,这就叫事件委托。

​ 事件委托可以大大减少操作DOM的次数,提高了代码的性能,减少了代码量。而且后面新创建的子元素,也能触发事件,执行事件处理函数。

// 案例代码

 <ul>
        <li>知否知否</li>
        <li>知否知否</li>
        <li>知否知否</li>
        <li>知否知否</li>
        <li>知否知否</li>
    </ul>
    <script>
        // 事件委托的核心原理:给父节点添加侦听器, 利用事件冒泡影响每一个子节点
        var ul = document.querySelector('ul');
        ul.addEventListener('click', function(e) {
            // e.target 这个可以得到我们触发事件的对象 然后对其进行操作
            e.target.style.backgroundColor = 'pink';
        })
    </script>

六、键盘事件

1、常用的键盘事件

① onkeyup

​ 当键盘某个按键被松开时触发。

② onkeydown

​ 当键盘某个按键被按下时触发,如果一直按着则一直触发。

③ onkeypress

​ 当键盘某个按键被按下时触发,如果一直按着则一直触发,但是不能识别功能键,比如ctrl、shift等。

**注意:**当使用 addEventListener 绑定事件时,要去掉前面的 on,只需要写 keyup、keydown、keypress 。而且当这三个事件同时存在时,是有一定的执行顺序:keydown --> keypress --> keyup,三者中 keyup 是最常用的。

// 案例代码

<script>
        // 常用的键盘事件
        // 1. keyup 按键弹起的时候触发 
        document.addEventListener('keyup', function() {
            console.log('我弹起了');
        })

        // 3. keypress 按键按下的时候触发  不能识别功能键 比如 ctrl shift 左右箭头啊
        document.addEventListener('keypress', function() {
                console.log('我按下了press');
        })
        // 2. keydown 按键按下的时候触发  能识别功能键 比如 ctrl shift 左右箭头啊
        document.addEventListener('keydown', function() {
                console.log('我按下了down');
        })
        // 4. 三个事件的执行顺序  keydown -- keypress -- keyup
		// 输出结果
		// 我按下了down --> 我按下了press --> 我弹起了
    </script>

2、键盘事件对象

​ 当键盘事件被触发时,会随之产生一个键盘事件对象,里面储存着很多与这次事件相关的属性信息,我们只需要了解部分属性:key 和 keyCode 。key 是获得 我们按下的是哪一个键,如果按 a 则返回 “a”,按 1 则返回 “1”,但这条属性有很大的兼容性问题,在很多浏览器都不支持,所以我们一般不用。

​ keyCode 是获得 我们按下键的ASCⅡ值,我们可以根据ASCⅡ值来判断按下的是哪一个键,但是要注意 onkeydown 和 onkeyup 是不区分字母大小写的,无论你按下大写的A 还是小写的 a 返回值都是 A 的65。而onkeypress 能区分字母的大小写,大小写不同,返回的ASCⅡ值 也不同。这条属性使我们常用的。

 <script>
        // 键盘事件对象中的keyCode属性可以得到相应键的ASCII码值
        document.addEventListener('keyup', function(e) {
            console.log('up:' + e.keyCode);
            // 我们可以利用keycode返回的ASCII码值来判断用户按下了那个键
            if (e.keyCode === 65) {
                alert('您按下的a键');
            } else {
                alert('您没有按下a键')
            }
        })
        document.addEventListener('keypress', function(e) {
            // console.log(e);
            console.log('press:' + e.keyCode);
        })
    </script>

你可能感兴趣的:(JavaScript基础,js,javascript)