web前端练习28----Dom4,事件(事件对象,事件冒泡,事件委派,事件传播,事件绑定,事件移除及案例练习)

Posted zhaihaohao1

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了web前端练习28----Dom4,事件(事件对象,事件冒泡,事件委派,事件传播,事件绑定,事件移除及案例练习)相关的知识,希望对你有一定的参考价值。

一、事件对象 event

1.1概念:

事件处理函数可以附加在各种对象上,包括 DOM元素,window 对象等。

当事件发生时, event 对象就会被创建并依次传递给事件监听器。

在处理函数中,将event对象作为第一个参数,可以访问 DOM Event 接口。

event 对象里有很多事件相关的属性和方法,例如事件,被点击元素对象target,创建时间,事件类型,坐标,path等

1.2event的常用属性:

event.target 触发事件的元素对象(就是事件目标)
event.clientX,event.clientY 鼠标触发的可见横纵坐标 
event.bubbles 事件是否冒泡
event.cancelBubble = true; 取消冒泡
event.eventPhase;1捕获,2目标,3冒泡
event.preventDefault(); 取消 addEventListener() 绑定事件的默认行为
event.type;被触发的事件的类型
event.wheelDelta 根据正负判断onmousewheel 事件向上还是向下滚动
event.detail 根据正负判断 DOMMouseScroll 事件向上还是向下滚动 (兼容火狐的)

键盘相关属性
event.key 获取按键
event.keyCode 获取按键的编码
event.altKey     alt是否被按下
event.ctrlKey    ctrl是否被按下
event.shiftKey  shift是否被按下

代码示例:

<html lang="en">

<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <meta http-equiv="X-UA-Compatible" content="ie=edge">
    <title>Document</title>
</head>

<body>
    <div id="eventId">事件测试</div>
    <script>
        //事件处理函数可以附加在各种对象上,包括 DOM元素,window 对象等。
        //当事件发生时, event 对象就会被创建并依次传递给事件监听器。
        //在处理函数中,将event对象作为第一个参数,可以访问 DOM Event 接口。
        //event 对象里有很多事件相关的属性和方法,例如事件,被点击元素对象target,创建时间,事件类型,坐标,path等
        let eventId = document.getElementById('eventId');
        eventId.onclick = function(event) 

            // ie8(及ie8以下)中拿到event要 window.event
            // 兼容ie8
            if (event) 
                console.log(event);
             else 
                event = window.event;
                console.log('ie8' + event);
            


            // if...else...写法的另一种写法,三目表达式
            // event = event ? event : window.event;
            // console.log(event);

            // if ...else...写法的另一种写法
            // event = event || window.event;
            // console.log(event);




        
    </script>

</body>

</html>

二、事件冒泡:

2.1事件冒泡的概念:

事件冒泡(Bubble)

所谓事件冒泡,就是事件向上传导,当后代元素上的事件被触发时,

其祖先元素的相同事件也会被触发(不管事件是否写出来)

开发中大部分冒泡是有用的,如果不需要冒泡,可以取消冒泡 event.cancelBubble = true; 

冒泡 span----div2----div1----body----html----document----window  

冒泡示意图:

事件冒泡代码示例:

<html lang="en">

<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <meta http-equiv="X-UA-Compatible" content="ie=edge">
    <title>Document</title>
</head>
<!-- 事件的冒泡 -->

<body id="body">
    <div id="div1" style="width: 300px;height: 300px; background-color: blue;">
        <div id="div2" style="width: 200px;height: 200px; background-color: red;">
            <span id="span" style="width: 100px;height: 100px; background-color: yellow;">我是span元素</span>
        </div>
    </div>
</body>
<script>
    // 事件冒泡 参考文章 https://blog.csdn.net/caseywei/article/details/86071764
    // 事件冒泡(Bubble)
    // 所谓事件冒泡,就是事件向上传导,当后代元素上的事件被触发时,
    // 其祖先元素的相同事件也会被触发(不管事件是否写出来)
    // 开发中大部分冒泡是有用的,如果不需要冒泡,可以取消冒泡 event.cancelBubble = true; 
    // 冒泡 span----div2----div1----body----html----document----window  
    let body = document.getElementById('body');
    let div1 = document.getElementById('div1');
    let div2 = document.getElementById('div2');
    let span = document.getElementById('span');
    body.onclick = function(event) 
        console.log(" 产生事件的节点:" + event.target.id + "  当前节点:" + event.currentTarget.id);
    
    div1.onclick = function(event) 
        console.log(" 产生事件的节点:" + event.target.id + "  当前节点:" + event.currentTarget.id);
    
    div2.onclick = function(event) 
        console.log(" 产生事件的节点:" + event.target.id + "  当前节点:" + event.currentTarget.id);
    
    span.onclick = function(event) 
        console.log(" 产生事件的节点:" + event.target.id + "  当前节点:" + event.currentTarget.id);
        // 取消冒泡
        event.cancelBubble = true;
    
</script>

</html>

三、事件委派(事件冒泡的应用)

3.1事件委派的概念:

事件委派:事件统一绑定给共同的父元素,子元素触发事件(不管事件是否写出来),会冒泡给父元素,

通过父元素的响应函数处理事件,根据 event.target,拿到子元素,判断处理逻辑

事件委派利用了事件冒泡,事件委派可以减少事件绑定的次数,提高程序性能

使用场景:父元素下面有多个子元素,都需要添加事件,我们通常需要一个一个添加(循环添加),而且新加的元素需要单独绑定事件

事件委派代码示例:

<html lang="en">

<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <meta http-equiv="X-UA-Compatible" content="ie=edge">
    <title>Document</title>

</head>

<body>
    <ul id="ulId">
        <li id="li1" class="classLI">zhh1</li>
        <li id="li2" class="classLI">zhh2</li>
        <li id="li3" class="classLI">zhh3</li>
        <li id="li4" class="classLI">zhh4</li>
        <li id="li5" class="classLI">zhh5</li>
    </ul>
    <script>
        // 事件的委派
        // 父元素下面有多个子元素,都需要添加事件,我们通常需要一个一个添加(循环添加),而且新加的元素需要单独绑定事件
        // 事件委派:事件统一绑定给共同的父元素,子元素触发事件(不管事件是否写出来),会冒泡给父元素,
        // 通过父元素的响应函数处理事件,根据 event.target,拿到子元素,判断处理逻辑
        // 事件委派利用了事件冒泡,事件委派可以减少事件绑定的次数,提高程序性能

        let ulId = document.getElementById('ulId');
        ulId.onclick = function(event) 
            //兼容ie8及以下
            event = event || window.event;
            // event.target 返回触发此事件的元素(事件的目标节点)。
            // 这里返回的就是 li
            if (event.target.nodeName == 'LI') 

                console.log(event.target.id);
            

        
    </script>

</body>

</html>

四、事件传播

4.1事件传播的概念:

- 事件传播分成了三个阶段

1.捕获阶段:- 在捕获阶段时从最外层的祖先元素,向目标元素进行事件的捕获,但是默认此时不会触发事件

2.目标阶段:- 事件捕获到目标元素,捕获结束开始在目标元素上触发事件

3.冒泡阶段:- 事件从目标元素向他的祖先元素传递,依次触发祖先元素上的事件

- 如果希望在捕获阶段就触发事件,可以将addEventListener()的第三个参数设置为true

一般情况下我们不会希望在捕获阶段触发事件,所以这个参数一般都是false

 - IE8及以下的浏览器中没有捕获阶段(只有目标阶段和冒泡阶段)

事件传播示意图:

代码示例:

<!DOCTYPE html>
<html>

<head>
    <meta charset="UTF-8">
    <title></title>
    <style type="text/css">
        #box1 
            width: 300px;
            height: 300px;
            background-color: yellowgreen;
        
        
        #box2 
            width: 200px;
            height: 200px;
            background-color: yellow;
        
        
        #box3 
            width: 150px;
            height: 150px;
            background-color: skyblue;
        
    </style>

    <script type="text/javascript">
        // 事件的传播
        window.onload = function() 

            /*
             * 分别为三个div绑定单击响应函数
             */
            var box1 = document.getElementById("box1");
            var box2 = document.getElementById("box2");
            var box3 = document.getElementById("box3");

            /*
             * 事件的传播
             * 	- 事件传播分成了三个阶段
             * 		1.捕获阶段
             * 			- 在捕获阶段时从最外层的祖先元素,向目标元素进行事件的捕获,但是默认此时不会触发事件
             * 		2.目标阶段
             * 			- 事件捕获到目标元素,捕获结束开始在目标元素上触发事件
             * 		3.冒泡阶段
             * 			- 事件从目标元素向他的祖先元素传递,依次触发祖先元素上的事件
             * 
             * 		- 如果希望在捕获阶段就触发事件,可以将addEventListener()的第三个参数设置为true
             * 			一般情况下我们不会希望在捕获阶段触发事件,所以这个参数一般都是false
             * 
             * 	- IE8及以下的浏览器中没有捕获阶段(只有目标阶段和冒泡阶段)
             */

            bind(box1, 'click', function() 
                alert('box1');
            );
            bind(box2, 'click', function() 
                alert('box2');
            );
            bind(box3, 'click', function() 
                alert('box3');
            );

        ;

        function bind(obj, eventStr, callback) 
            if (obj.addEventListener) 
                // 大部分浏览器兼容的方式
                // 如果希望在捕获阶段就触发事件,可以将addEventListener()的第三个参数设置为true
                // 一般情况下我们不会希望在捕获阶段触发事件,所以这个参数一般都是false
                obj.addEventListener(eventStr, callback, true);
             else 
                /*
                 * this是谁由调用方式决定
                 * callback.call(obj)
                 */
                //IE8及以下
                obj.attachEvent("on" + eventStr, function() 
                    //在匿名函数中调用回调函数
                    callback.call(obj);
                );
            
        
    </script>
</head>

<body>

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

</body>

</html>

五、事件的绑定

5.1事件的两种绑定方式:

5.11只能绑定一个响应函数:

         divId.onclick = function()
             console.log('我是翟浩浩');
         

5.12绑定多个响应函数:

         divId.addEventListener('click',function()
             alert(1);
         ,false);
         divId.addEventListener('click',function()
             alert(2);
         ,false);
         divId.addEventListener('click',function()
             alert(3);
         ,false);

5.13绑定多个响应函数,兼容ie8及以下

绑定多个响应函数,和 addEventListener 不同的是,后绑定的先执行

        divId.attachEvent('onclick', function() 
            alert(1);

        );
        divId.attachEvent('onclick', function() 
            alert(2);

        );

        divId.attachEvent('onclick', function() 
            alert(3);

        );

绑定多个响应事件代码示例:

<!DOCTYPE html>
<html lang="en">

<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <meta http-equiv="X-UA-Compatible" content="ie=edge">
    <title>Document</title>
</head>

<body>

    <div id="divId">点击事件</div>

    <script>
        // 事件绑定封装兼容ie8的函数 myBind
        var divId = document.getElementById('divId');
        myBind(divId, 'click', function() 
            // 直接打印出来的是对象的类型
            console.log(this);
            console.log(111);
          

        );
        myBind(divId, 'click', function() 
            // 直接打印出来的是对象的类型
            console.log(this);
            console.log(222);
          

        );

        // 自己封装一个函数兼容,ie8以下,及别的浏览器
        function myBind(obj, eventString, callBack) 
            if (obj.addEventListener) 
                // 其它其它浏览器
                obj.addEventListener(eventString, callBack, false);
             else 
                // ie8及以下浏览器,这个回调函数中的this,指向的是window,要使用call指向obj
                obj.attachEvent('on' + eventString, function() 
                    callBack.call(obj)
                );
            
        
    </script>

</body>

</html>

5.2取消事件默认行为的方法:

默认行为:比如
1.a元素的跳转行为,绑定点击事件后还能跳转 a.onclick
2.浏览器内容较大时,上下滚动行为 box1.onmousewheel
3.输入框显示输入内容的行为,input.onkeydown 

5.21取消默认行为:aId.onclick = function() 只要 reurn false; 就可以取消

<body>
    <a id="aId" href="https://www.baidu.com/">点击链接</a>
    <script>
        // 键盘事件
        let aId = document.getElementById('aId');
        aId.onclick = function () 
            return false;
        
    </script>
</body>

5.22取消默认行为:box1.addEventListener('DOMMouseScroll', fun, false); 需要 event.preventDefault();  即可取消

<body>
    <a id="aId"  href="https://www.baidu.com/">点击链接</a>
    <script>
        // 键盘事件
        let aId = document.getElementById('aId');
        aId.addEventListener('click',function(event)
           console.log('事件点击了');
           event.preventDefault();
        ,false);
    </script>
</body>

六、事件的移除:

 对应:btn.onclick = function() 所有浏览器都可以
 btn.οnclick=null;
 对应:addEventListener 兼容ie9及以上
 btn.removeEventListener('click', btnClick);

七、案例练习:

7.1  拖拽练习

onmousedown 鼠标按下,   onmousemove 鼠标移动,  onmouseup 鼠标放开

利用上面三个事件完成拖拽练习,效果图如下:

事件拖拽的坐标计算

代码如下:

<!DOCTYPE html>
<html lang="en">

<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <meta http-equiv="X-UA-Compatible" content="ie=edge">
    <title>Document</title>
    <style>
        #box1 
            width: 100px;
            height: 100px;
            background-color: red;
            position: absolute;
        
        
        #box2 
            width: 100px;
            height: 100px;
            background-color: yellow;
            position: absolute;
            left: 300px;
        
    </style>
</head>

<body>
    <p>测试</p>
    <div id="box1">方块1</div>
    <div id="box2">方块2</div>

    <script>
        //拖拽练习3
        var box1 = document.getElementById('box1');
        var box2 = document.getElementById('box2');
        drop(box1);
        drop(box2);

        // 自己封装的拖拽函数
        function drop(obj) 
            // 绑定按下事件:
            obj.onmousedown = function(event) 
                event = event || window.event;

                console.log('onmousedown');
                // 左边div偏移量 = 鼠标.clientX - 元素.offsetLeft;
                // 上边div偏移量 = 鼠标.clientY - 元素.offsetTop;
                var oLeft = event.clientX - obj.offsetLeft;
                var oTop = event.clientY - obj.offsetTop;

                // 鼠标滑动事件,给 document 绑定
                document.onmousemove = function(event) 
                        console.log('onmousemove');
                        // 兼容ie8
                        event = event || window.event;
                        var left = event.clientX - oLeft;
                        var top = event.clientY - oTop;
                        // 设置外边距
                        obj.style.left = left + 'px';
                        obj.style.top = top + 'px';
                    
                    // 鼠标放开事件,给docment绑定
                document.onmouseup = function() 
                        console.log('onmouseup');
                        // 终止移动事件
                        document.onmousemove = null;
                        // 终止鼠标放开事件
                        document.onmouseup = null;
                    
                    /*
                     * 当我们拖拽一个网页中的内容时,浏览器会默认去搜索引擎中搜索内容,
                     * 	此时会导致拖拽功能的异常,这个是浏览器提供的默认行为,
                     * 	如果不希望发生这个行为,则可以通过return false来取消默认行为
                     * 
                     * 但是这招对IE8不起作用
                     */
                return false;
            

        
    </script>
</body>

</html>

7.2滚轮练习,要求:鼠标滚轮滚动,改变方块的宽高

onmousewheel 监听鼠标滚轮事件

效果图:

代码如下:

<!DOCTYPE html>
<html lang="en">

<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <meta http-equiv="X-UA-Compatible" content="ie=edge">
    <title>Document</title>
    <style>
        * 
            margin: 0px;
            padding: 0px;
        
        
        #box1 
            width: 100px;
            height: 100px;
            background-color: red;
            position: absolute;
        
    </style>
</head>

<body style="height: 2000px;">
    <!-- 滚轮练习 -->
    <p>测试</p>
    <div id="box1">方块1</div>

    <script>
        let box1 = document.getElementById('box1');
        // 其他其他浏览器的滚轮事件
        box1.onmousewheel = fun;
        // 火狐浏览器的滚轮事件
        box1.addEventListener('DOMMouseScroll', fun, false);

        function fun(event) 
            // 兼容ie8
            event = event || window.event;
            console.log(event);


            //event.wheelDelta 可以获取鼠标滚轮滚动的方向
            //向上滚 120   向下滚 -120
            //wheelDelta这个值我们不看大小,只看正负


            // 兼容火狐 
            //在火狐中使用event.detail来获取滚动的方向
            //向上滚 -3  向下滚 3
            //event.detail 这个值我们不看大小,只看正负

            if (event.wheelDelta > 0 || event.detail < 0) 

                let height = box1.clientHeight;
                if (height > 30) 
                    box1.style.height = box1.clientHeight - 10 + 'px';
                

             else 
                box1.style.height = box1.clientHeight + 10 + 'px';
            

            /*
             * 使用addEventListener()方法绑定响应函数,取消默认行为时不能使用return false
             * 需要使用event来取消默认行为event.preventDefault();
             * 但是IE8不支持event.preventDefault();这个玩意,如果直接调用会报错
             * 所以这里要判断
             */
            if (event.preventDefault) 
                event.preventDefault();
            
            /*
             * 当滚轮滚动时,如果浏览器有滚动条,滚动条会随之滚动,
             * 这是浏览器的默认行为,如果不希望发生,则可以取消默认行为 return false;
             */
            return false;
        
    </script>

</body>

</html>

7.3键盘事件:

键盘事件最常用的就是 onkeydown 按键按下  onkeyup 按键松开

键盘事件一般都会绑定给一些可以获取到焦点(光标)的对象或者是document

比如说 input 绑定 onkeydown 输入框有光标时被才能被触发

键盘事件代码示例:

<!DOCTYPE html>
<html lang="en">

<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <meta http-equiv="X-UA-Compatible" content="ie=edge">
    <title>Document</title>
</head>

<body>
    <input type="text" name="zhh" id="inputId">

    <script>
        // 键盘事件
        // 键盘事件最常用的就是 onkeydown 按键按下  onkeyup 按键松开
        // 键盘事件一般都会绑定给一些可以获取到焦点(光标)的对象或者是document
        // 比如说 input 绑定 onkeydown 输入框有光标时被才能被触发
        let inputId = document.getElementById('inputId');
        /*
         * 可以通过keyCode来获取按键的编码
         * 	通过它可以判断哪个按键被按下
         * 除了keyCode,事件对象中还提供了几个属性
         * 	altKey
         * 	ctrlKey
         * 	shiftKey
         * 		- 这个三个用来判断alt ctrl 和 shift是否被按下
         * 			如果按下则返回true,否则返回false
         */

        // inputOnkeyDown();
        docmentOnKeyDown();

        function inputOnkeyDown() 
            // 给 input 绑定onkeydown事件
            // input 绑定 onkeydown 输入框有光标时被才能被触发
            inputId.onkeydown = function(event) 
                // 兼容ie8及以下
                event = event || window.event;

                console.log(event.keyCode);
                // enter是13
                if (event.keyCode === 13) 
                    console.log('按键enter');
                
                if (event.altKey) 
                    console.log('按键alt');
                
                if (event.ctrlKey) 
                    console.log('按键ctrl');

                
                if (event.shiftKey) 
                    console.log('按键shift');
                

                //判断enter和ctrl是否同时被按下
                if (event.keyCode === 13 && event.ctrlKey) 
                    console.log("ctrl和y都被按下了");
                
            
        

        function docmentOnKeyDown() 
            // 给 docment 绑定onkeydown事件
            // document 绑定 onkeydown 只要按键就能触发
            document.onkeydown = function(event) 
                // 兼容ie8及以下
                event = event || window.event;
                console.log(event.keyCode);
                //过滤掉数字
                //数字 48 - 57
                //使文本框中不能输入数字
                if (event.keyCode >= 48 && event.keyCode <= 57) 
                    //在文本框中输入内容,属于onkeydown的默认行为
                    //如果在onkeydown中取消了默认行为,则输入的内容,不会出现在文本框中
                    return false;
                

            
        
    </script>
</body>

</html>

键盘事件 onkeydown  onkeyup

键盘事件练习

按键键盘上的 上,下,左,右 实现方块的移动

效果图:

代码示例:

<!DOCTYPE html>
<html lang="en">

<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <meta http-equiv="X-UA-Compatible" content="ie=edge">
    <title>Document</title>
    <style>
        * 
            margin: 0px;
            padding: 0px;
        
        
        div 
            width: 100px;
            height: 100px;
            background-color: red;
            position: absolute;
        
    </style>
</head>

<body>
    <div id="div">键盘事件</div>
    <script>
        // 练习 键盘移动 div
        let div = document.getElementById('div');
        // 设置一个加速器,减速器
        let speed = 10;


        document.onkeydown = function(event) 
            // 兼容ie8及以下
            event = event || window.event;

            // 按加号加速
            if (event.keyCode == 187) 
                speed = 50;
            
            // 按减号减速
            if (event.keyCode == 189) 
                speed = 10;
            
            // event.keyCode 37左 39右 38上40下 
            if (event.keyCode == 37) 
                div.style.left = div.offsetLeft - speed + 'px';
            
            if (event.keyCode == 39) 
                div.style.left = div.offsetLeft + speed + 'px';
            
            if (event.keyCode == 38) 
                div.style.top = div.offsetTop - speed + 'px';
            
            if (event.keyCode == 40) 
                div.style.top = div.offsetTop + speed + 'px';
            

            console.log(speed);


        
    </script>
</body>

</html>

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

以上是关于web前端练习28----Dom4,事件(事件对象,事件冒泡,事件委派,事件传播,事件绑定,事件移除及案例练习)的主要内容,如果未能解决你的问题,请参考以下文章

好程序员web前端教程分享前端javascript练习题

从零开始学 Web 之 jQuery事件冒泡,事件参数对象,链式编程原理

小白入门之前端网页技术JQuery

前端开发——综述

事件对象练习

[Web 前端] 028 jQuery 事件