js基础十七-- 事件对象、事件委托、事件分类

一、事件对象

event || window.event
事件源对象:
event.target 火狐、谷歌
event.srcElement Ie、谷歌

target和srcElement是事件对象event身上的两个属性,记录着事件触发的源头(事件源对象)

例如:

<!DOCTYPE html>
<html>
    <head>
        <meta charset="utf-8">
        <title>文档标题</title>
        <style type="text/css">
            .wrapper {
                width: 200px;
                height: 200px;
                background-color: red;
            }

            .content {
                width: 100px;
                height: 100px;
                background-color: black;
            }

            .box {
                width: 50px;
                height: 50px;
                background-color: #ccc;
            }
        </style>
    </head>
    <body>
        <div class="wrapper">
            <div class="content">
                <div class="box"></div>
            </div>
        </div>
        <script type="text/javascript">
            var wrapper = document.getElementsByClassName("wrapper")[0];
            var content = wrapper.children[0];
            var box = content.children[0];

            box.onclick = function(e) {
                console.log(e.target);    // 打印事件源对象
                console.log("a");
                e.stopPropagation();    // 阻止事件冒泡
            }

            content.onclick = function(e) {
                console.log(e.target);  // 打印事件源对象
                console.log("b");
                e.stopPropagation();    // 阻止事件冒泡
            }
            
            wrapper.onclick = function(e) {
                console.log(e.target);  // 打印事件源对象
                console.log("c");
            }
        </script>
    </body>
</html>

点击box,打印后的事件源对象为:

点击content,打印后的事件源对象为:

点击wrapper,打印后的事件源对象为:

二、事件委托

// 利用事件冒泡,和事件源对象进行处理 

//【优点】:
//  1、提高性能,不需要循环所有的元素一个个绑定事件
//  2、灵活当有新的子元素时,不需要重新绑定事件

先来看一个简单案例

<!DOCTYPE html>
<html>
    <head>
        <meta charset="utf-8">
        <title>文档标题</title>
    </head>
    <body>
        <ul>
            <li>1</li>
            <li>2</li>
            <li>3</li>
            <li>4</li>
            <li>5</li>
            <li>6</li>
            <li>7</li>
            <li>8</li>
            <li>9</li>
            <li>10</li>
        </ul>
        <script type="text/javascript">
            // 事件委托
            // 要求,给每个li注册点击事件并输出每个li的内容
            var ul = document.getElementsByTagName("ul")[0];

            ul.onclick = function(e) {
                var event = e || window.event;         // 兼容IE
                var target = e.target || e.srcElement; // 获取事件源对象
                console.log(target.innerText);         // 打印出事件源对象的文本内容
            }
        </script>
    </body>
</html>

通过获取父级,将事件委托(冒泡)给父级对象,并通过获取事件源对象的文本内容,来得到相应结果。减少多余的循环操作,提高性能、优化代码。

控制台打印结果如下:

三、事件分类

鼠标事件

// 【鼠标事件】
//  click(点击)、mousedown(按下)、mousemove(移动)、mouseup(抬起)、mouseover(鼠标进入)、mouseout(鼠标移出)、mouseenter(鼠标进入h5)、mouseleave(鼠标移出h5)、contextmenu(右键菜单)

事件对象中有一个属性button用来区分鼠标的按键 0(左)/1(中)/2(右)

注意:DOM3标准规定:click事件只能监听左键,只能通过mousedown或者mouseup来判断鼠标键

如何解决mousedown和click冲突? 我们可以利用时间戳来判断是点击还是拖拽。

var firstTime,
      lantTime,
      key = false;
document.onmousedown = function(e) {
    firstTime = new Date().getTime();  // 鼠标按下时获取最新时间
  // document.onmousemove...
} document.onmouseup
= function(e) { lantTime = new Date().getTime(); // 鼠标抬起时再次获取最新时间 if (lantTime - firstTime < 300) { // 如果鼠标抬起时间小于300,则判断为点击事件,执行点击事件里的事件处理程序,如果大于或等于300则执行拖拽事件 key = true; } } document.onclick = function(e) { if (key) { console.log("点击事件"); key = false; } }

键盘类事件

// 【键盘事件】
// keydown(键盘按下)、keyup(键盘抬起)、keypress (键盘按下)

来看一下上面三个事件在控制台的反应速度:

// keydown > keypress > keyup
document.onkeypress = function(e) { console.log("onkeypress"); } document.onkeydown = function(e) { console.log("onkeydown"); } document.onkeyup = function(e) { console.log("onkeyup"); }

按下任意键,控制台反应结果:

//【keydown和keypress区别】
// keydown可以响应任意键盘按键,keypress只可以响应字符类键盘按键,keypress可以返回asscll码,可以转换成相应字符

打印两个事件的事件对象:

document.onkeypress = function(e) {
    console.log(e);
}
document.onkeydown = function(e) {
    console.log(e);
}

按下键盘上字母k后,控制台事件对象的返回结果为:

因此直接打印两个事件返回的asscll码:

document.onkeypress = function(e) {
    console.log(e.charCode);
}
document.onkeydown = function(e) {
    console.log(e.charCode);
}

控制台返回结果为:

因此,当我们得到返回的asscll码后,可以通过字符串方法String.fromCharCode();将asscll码转换成对应的按键名

document.onkeypress = function(e) {
    console.log(String.fromCharCode(e.charCode));
}

控制台输入对应按键以及按shift输入对应键,打印结果如下:

文本操作事件

// 【文本操作事件】
// input(文本变化监听)、change(失去焦点并且状态发生改变时触发)
//
focus(获得焦点时触发) 、blur(失去焦点时触发)

来看实际例子:

<input type="text">
<script type="text/javascript">
    var input = document.getElementsByTagName("input")[0];
    input.oninput = function(e) {
        console.log(this.value);
    }
    input.onchange = function(e) {
        console.log(this.value);
    }
</script>

查看控制台监听结果:

// 【提示】:onfocus 事件的相反事件为 onblur 事件
<input type="text" value="请输入用户名" onfocus="if(this.value=='请输入用户名'){this.value = '';this.style.color = '#424242';}" onblur="if(this.value == ''){this.value = '请输入用户名';this.style.color='#999'}" >

窗体操作类事件

窗体操作类(window)事件:scroll、load【重要】--不建议用、效率低

移动端事件汇总 

 移动端事件:touchstart、touchmove、touchend
 1. click事件
 单击事件,类似于PC端的click,但在移动端中,连续click的触发有200ms ~ 300ms的延迟
  
 2. touch类事件
 触摸事件,有touchstart touchmove touchend touchcancel 四种之分
 touchstart:手指触摸到屏幕会触发
 touchmove:当手指在屏幕上移动时,会触发
 touchend:当手指离开屏幕时,会触发
 touchcancel:可由系统进行的触发,比如手指触摸屏幕的时候,突然alert了一下,或者系统中其他打断了touch的行为,则可以触发该事件
 
 3. tap类事件
 触碰事件,我目前还不知道它和touch的区别,一般用于代替click事件,有tap longTap singleTap doubleTap四种之分
 tap: 手指碰一下屏幕会触发
 longTap: 手指长按屏幕会触发
 singleTap: 手指碰一下屏幕会触发
 doubleTap: 手指双击屏幕会触发
 
 4. swipe类事件
 滑动事件,有swipe swipeLeft swipeRight swipeUp swipeDown 五种之分
 swipe:手指在屏幕上滑动时会触发
 swipeLeft:手指在屏幕上向左滑动时会触发
 swipeRight:手指在屏幕上向右滑动时会触发
 swipeUp:手指在屏幕上向上滑动时会触发
 swipeDown:手指在屏幕上向下滑动时会触发

案例:封装拖拽函数drag(elem);

<!DOCTYPE html>
<html>
    <head>
        <meta charset="utf-8">
        <title>文档标题</title>
        <style type="text/css">
            .box {
                width: 100px;
                height: 100px;
                background-color: red;
                position: absolute;
                left: 0;
                top: 0;
            }

            .content {
                width: 200px;
                height: 200px;
                background-color: blue;
                position: absolute;
                left: 0;
                top: 0;
            }
        </style>
    </head>
    <body>

        <div class="content"></div>
        <div class="box"></div>
        <!-- 引入外部工具js -->
        <script src="js/Tools.js" type="text/javascript" charset="utf-8"></script>
        <script type="text/javascript">
            // 获取DOM
            var content = document.getElementsByClassName("content")[0];
            var box = document.getElementsByClassName("box")[0];

            // 封装拖拽函数
            function drag(elem) {
                // 1、获取浏览器可见区域宽高,元素宽高
                var browserWidth = document.documentElement.clientWidth,
                    browserHeight = document.documentElement.clientHeight,
                    elemWidth = elem.offsetWidth,
                    elemHeight = elem.offsetHeight;

                // 3.1 移动事件处理程序
                function mouseMove(e) {
                    var event = e || window.event; // // 兼容IE
                    var target = e.target || e.srcElement;
                    // 目标元素距离左侧距离 = 移动中鼠标点距离文档左侧的距离 - 鼠标相对于目标元素左侧距离
                    elem.style.left = (e.clientX - disX) + "px";
                    // 判断目标元素是否移出浏览器可视区域
                    if ((e.clientX - disX) <= 0) {
                        elem.style.left = 0;
                    } else if ((elemWidth - disX + e.clientX) >= browserWidth) {
                        elem.style.left = browserWidth - elemWidth + "px";
                    }
                    // 目标元素距离顶部距离 = 移动中鼠标点距离文档顶部的距离 - 鼠标相对于目标元素顶部距离
                    elem.style.top = (e.clientY - disY) + "px";
                    // 判断目标元素是否移出浏览器可视区域
                    if ((e.clientY - disY) <= 0) {
                        elem.style.top = 0;
                    } else if ((elemHeight - disY + e.clientY) >= browserHeight) {
                        elem.style.top = browserHeight - elemHeight + "px";
                    }
                }
                // 3.2 移动事件处理程序
                function mouseUp(e) {
                    var event = e || window.event;
                    // 4、移除鼠标移动、抬起事件以及相关事件处理程序
                    removeEvent(document, "mousemove", mouseMove); // 清除鼠标移动事件以及事件处理程序
                    removeEvent(document, "mouseup", mouseUp); // 清除鼠标抬起事件以及事件处理程序
                }

                var disX,
                    disY;
                addEvent(elem, "mousedown", function(e) {
                    var event = e || window.event;
                    // 2、记录鼠标相对于目标元素左侧以及顶部距离
                    disX = e.clientX - this.offsetLeft;
                    disY = e.clientY - this.offsetTop;
                    // 3、以整个文档为目标,建立鼠标移动、抬起事件并设置相关事件处理程序
                    addEvent(document, "mousemove", mouseMove); // 添加鼠标移动事件以及事件处理程序
                    addEvent(document, "mouseup", mouseUp); // 添加鼠标移动事件以及事件处理程序
                    stopBubble(event); // 阻止冒泡
                    cancelHandler(event); // 阻止默认事件
                });
            }
            // 调用拖拽函数
            drag(box);
            drag(content);
        </script>
    </body>
</html>

 

posted @ 2021-05-11 12:02  半白半黑  阅读(231)  评论(0)    收藏  举报