JavaScript——事件对象和事件委托

133 阅读7分钟

持续创作,加速成长!这是我参与「掘金日新计划 · 10 月更文挑战」的第23天,点击查看活动详情

就是当你触发了一个事件以后,对该事件的一些描述信息

例如:

  1. 你触发一个点击事件的时候,你点在哪个位置了,坐标是多少
  2. 你触发一个键盘事件的时候,你按的是哪个按钮

• 每一个事件都会有一个对应的对象来描述这些信息,我们就把这个对象叫做 事件对象

• 浏览器给了个 window.event ,就是对事件信息的所有描述

• 我们就得用另一种方式来获取 事件对象,在每一个事件处理函数的行参位置,默认第一个就是 事件对象

事件对象

1.什么是事件对象

任何事件触发后将会产生一个事件对象,跟事件相关的一系列信息数据的集合都放到这个对象里面。比如: ①谁绑定了这个事件。 ②如果是鼠标触发事件,会得到鼠标的相关信息,如鼠标位置。(对应的事件对象叫鼠标事件对象) ③如果是键盘触发事件,会得到键盘的相关信息,如按了哪个键。(对应的事件对象叫键盘事件对象)

2.事件对象的获取

事件触发时就会产生一个事件对象,系统会以实参的形式将这个事件对象传给事件处理函数。 所以,在事件处理函数中需要声明一个形参用来接收事件对象。

var btn2 = document.getElementById('btnId2');
btn2.onclick = function(event) { //这个event就是事件对象,也经常写成e或evt。
    alert('捉老鼠二号');
}
​
var btn4 = document.getElementById('btnId4');
btn4.addEventListener('click', function(event) { //这个event就是事件对象,也经常写成e或evt。
    alert('捉老鼠四号');
})
​
btn4.addEventListener('click', catchFunc);
function catchFunc(event) { //这个event就是事件对象,也经常写成e或evt。
    alert('捉老鼠');
}

事件对象的获取存在的兼容问题:

a.标准浏览器中是浏览器给方法传递的参数,只需要定义形参 e 就可以获取到。

标准浏览器泛指对W3C所定义的CSS2.1规范提供了优秀支持并能完美呈现的浏览器。
目前的标准浏览器包括:Opera 10.10、Safari 4.0.4、Intelnet Explorer 9、Firefox 3、Chrome。
您也可以对自己的浏览器进行验证,方法如下:
在浏览器的地址栏中复制以下地址 http://www.webstandards.org/files/acid2/test.html#top,
若能看到一张笑脸,则您的浏览器是标准浏览器。

b.在 IE6~8 中,浏览器不会给方法传递参数,我们需要通过 window.event 获取。

注意,对于标准浏览器, window.event也能获取到事件对象。

兼容问题的解决方案:

<div style="height: 25px;width: 300px;background-color: pink;">我是一个div</div><script>
    var div = document.querySelector('div');
    div.onclick = function(e) {
        //只要“||”前面为false, 不管“||”后面是true 还是 false,都返回 “||” 后面的值。
        //只要“||”前面为true, 不管“||”后面是true 还是 false,都返回 “||” 前面的值。
        e = e || window.event; // 事件对象
        console.log(e);
    }
</script>

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

属性和方法说明
e.target返回事件源(标准浏览器)
e.srcElement返回事件源(非标准浏览器,在 IE6~8 中)
e.type返回事件类型
e.stopPropagation()阻止事件冒泡(标准浏览器)
e.cancelBubble阻止事件冒泡(非标准浏览器,在 IE6~8 中,true)
e.preventDefault()阻止默认事件(标准浏览器) 默认事件==默认行为,比如不让链接跳转。
e.returnValue阻止默认事件(非标准浏览器,在 IE6~8 中,false) 默认事件==默认行为,比如不让链接跳转。
1.e.target 和 this 的区别

1.e.target 是事件触发的元素,即事件源。this 是事件绑定的元素(绑定这个事件处理函数的元素) 。一般情况下二 者是一致的。

<div style="height: 25px;width: 300px;background-color: pink;">我是一个div</div><script>
    var div = document.querySelector('div');
    div.onclick = function(e) {
        e = e || window.event; // 事件对象
        console.log(e.target); //div元素
        console.log(this); //div元素
    }
</script>

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

<div style="height: 25px;width: 300px;background-color: pink;">我是一个div
    <button type="button">我是一个button</button>
</div><script>
    var div = document.querySelector('div');
    div.onclick = function(e) {
        e = e || window.event; // 事件对象
        console.log(e.target); //button元素
        console.log(this); //div元素
    }
</script>
2.阻止事件冒泡
<div class="father">大盒子
    <div class="son">小盒子</div>
</div>
​
<script>
    var son = document.querySelector('.son');
    son.onclick = function(e) {
        alert('您点击了小盒子');
        // 1.以下这种写法对标准浏览器起作用
        //e.stopPropagation(); //阻止事件冒泡(标准浏览器)
        // 2.以下这种写法对非标准浏览器起作用
        //window.event.cancelBubble = true; //阻止事件冒泡(非标准浏览器,在 IE6~8 中)
        /* 3.阻止事件冒泡的兼容性处理 */
        if (e && e.stopPropagation) {
            e.stopPropagation(); //阻止事件冒泡(标准浏览器)
        } else {
            window.event.cancelBubble = true;//阻止事件冒泡(非标准浏览器,在 IE6~8 中)
        }
        
        // 4.注意以下这种写法不能阻止事件冒泡。
        // return false;
        
        /* 5.测试发现以下两种写法对标准浏览器也起作用 */
        //e.cancelBubble = true; 
        //window.event.cancelBubble = true; //阻止事件冒泡(非标准浏览器,在 IE6~8 中)
        // 6.测试发现以下这种写法对非标准浏览器不起作用,运行到这一行报错了。
        e.stopPropagation(); //阻止事件冒泡(标准浏览器)
    }
    var father = document.querySelector('.father');
    father.onclick = function() {
        alert('您点击了大盒子');
    }
</script>
3.阻止默认行为

1.HTML中一些标签有默认行为,例如a标签被单击后,默认会进行页面跳转。

<a href="http://www.baidu.com">百度</a>
​
<script>
    var a = document.querySelector('a');
    a.onclick = function(e) {
        // 1.以下这种写法对标准浏览器起作用
        // e.preventDefault(); //阻止默认事件(标准浏览器)
        // 2.以下这种写法对非标准浏览器起作用
        // window.event.returnValue = false; //阻止默认事件(非标准浏览器,在 IE6~8 中,false)
        /* 3.阻止默认行为的兼容性处理 */
        // if (e && e.preventDefault) {
        //  e.preventDefault(); //阻止默认事件(标准浏览器)
        // } else {
        //  window.event.returnValue = false;//阻止默认事件(非标准浏览器,在 IE6~8 中,false)
        // }
​
        // 4.以下这种写法也能阻止默认行为,且没有兼容性问题。
        return false;
​
        /* 5.测试发现以下两种写法对除IE以外的标准浏览器也起作用 */
        // e.returnValue = false;
        // window.event.returnValue = false; //阻止默认事件(非标准浏览器,在 IE6~8 中,false)
        // 6.测试发现以下这种写法对非标准浏览器不起作用。
        // e.preventDefault(); //阻止默认事件(标准浏览器)
    }
</script>

2.网页中的鼠标的一些默认行为,例如鼠标右键菜单、鼠标选中。

<h1>1.本网页禁用了鼠标右键菜单</h1>
<h1>2.本网页禁止了鼠标选中文字</h1><script>
    /* 1.oncontextmenu 主要控制何时显示上下文菜单,主要用于程序员取消默认的上下文菜单。 */
    document.oncontextmenu = function(e) {
        // 1.以下这种写法对标准浏览器起作用
        // e.preventDefault(); //阻止默认事件(标准浏览器)
        // 2.以下这种写法对非标准浏览器起作用
        // window.event.returnValue = false; //阻止默认事件(非标准浏览器,在 IE6~8 中,false)
        /* 3.阻止默认行为的兼容性处理 */
        // if (e && e.preventDefault) {
        //     e.preventDefault(); //阻止默认事件(标准浏览器)
        // } else {
        //     window.event.returnValue = false; //阻止默认事件(非标准浏览器,在IE6~8中false)
        // }
​
        // 4.以下这种写法也能阻止默认行为,且没有兼容性问题。
        return false;
​
        /* 5.测试发现以下两种写法对除IE以外的标准浏览器也起作用 */
        // e.returnValue = false;
        // window.event.returnValue = false; //阻止默认事件(非标准浏览器,在 IE6~8 中,false)
        // 6.测试发现以下这种写法对非标准浏览器不起作用,运行到这一行报错了。
        // e.preventDefault(); //阻止默认事件(标准浏览器)
​
    }
    /* 2.onselectstart 触发时间为目标对象被开始选中时(即选中动作刚开始,尚未实质性被选中)。 */
    document.onselectstart = function(e) {
        // 1.以下这种写法对标准浏览器起作用
        // e.preventDefault(); //阻止默认事件(标准浏览器)
        // 2.以下这种写法对非标准浏览器起作用
        // window.event.returnValue = false; //阻止默认事件(非标准浏览器,在 IE6~8 中,false)
        /* 3.阻止默认行为的兼容性处理 */
        // if (e && e.preventDefault) {
        //     e.preventDefault(); //阻止默认事件(标准浏览器)
        // } else {
        //     window.event.returnValue = false; //阻止默认事件(非标准浏览器,在IE6~8中false)
        // }
​
        // 4.以下这种写法也能阻止默认行为,且没有兼容性问题。
        return false;
​
        /* 5.测试发现以下两种写法对除IE以外的标准浏览器也起作用 */
        // e.returnValue = false;
        // window.event.returnValue = false; //阻止默认事件(非标准浏览器,在 IE6~8 中,false)
        // 6.测试发现以下这行对非标准浏览器也起作用(与上面oncontextmenu情况相反),运行到这一行报错了。
        // e.preventDefault(); //阻止默认事件(标准浏览器)
}
</script>

3.网页中禁止通过F12按键打开开发者工具(注意,仍然可以通过鼠标点击的相应菜单的操作来打开)

document.onkeydown = function(e) {
    var currKey = 0,e = e || window.event;
    //获取按下的按键,兼容性的写法,不同的浏览器有不同的支持。有些浏览器不支持e.keyCode,则用e.which。
    currKey = e.keyCode || e.which || e.charCode;
    console.log(currKey);//按下F12之后,将获取到123(F12键的ASCII码值)。
    //HbuilderX内置浏览器:123-谷歌:123-火狐:123-Edg:123-IE11:123-IE8:123
    console.log(e.keyCode); 
    //HbuilderX内置浏览器:123-谷歌:123-火狐:123-Edg:123-IE11:123-IE8:undefined
    console.log(e.which);   
    //HbuilderX内置浏览器:0---谷歌:0---火狐:0---Edg:0---IE11:0---IE8:undefined
    console.log(e.charCode);
    if (currKey == 123) {
        window.event.cancelBubble = true; //阻止事件冒泡(非标准浏览器,在 IE6~8 中)
        window.event.returnValue = false; //阻止默认事件(非标准浏览器,在 IE6~8 中,false)
        //e.stopPropagation();
        //e.preventDefault();
    }
}

4.鼠标事件对象的属性

以下列举了鼠标事件对象中,获取鼠标在页面的坐标的相关属性。

鼠标事件对象属性说明
e.clientX返回鼠标相对于浏览器窗口可视区的X坐标
e.clientY返回鼠标相对于浏览器窗口可视区的Y坐标
e.pageX返回鼠标相对于文档页面的X坐标(IE9+支持)
e.pageY返回鼠标相对于文档页面的Y坐标(IE9+支持)
e.ScreenX返回鼠标相对于电脑屏幕的X坐标
e.ScreenY返回鼠标相对于电脑屏幕的Y坐标
1.通过事件对象获取鼠标的坐标
document.onclick = function(e) { //e此时是事件对象的细类——鼠标事件对象
    e = e || window.event;
    console.log('1.鼠标在浏览器窗口可视区的x和y坐标:');
    console.log(e.clientX);
    console.log(e.clientY);
    console.log('2.鼠标在文档页面的x和y坐标:');
    console.log(e.pageX); //IE9+支持
    console.log(e.pageY); //IE9+支持
    console.log('3.鼠标在电脑屏幕的x和y坐标:');
    console.log(e.screenX);
    console.log(e.screenY);
}
注:IE9+表示IE9及其以上。
2.跟随鼠标案例
<style>
    img {
        position: absolute;
        top: 3px;
    }
</style><img src="img/bee.gif" alt="">
    
<script>
    var img = document.querySelector('img');
    /* onmousemove:鼠标移动触发,只要鼠标移动1px,就会触发该事件。*/
    document.onmousemove = function(e) { 
        /* 1.获取最新的鼠标坐标 */
        var x = e.clientX;
        var y = e.clientY;
        console.log('x坐标是' + x, 'y坐标是' + y);
        /* 2.根据鼠标坐标设置图片的位置 */
        img.style.left = x - 20 + 'px';
        img.style.top = y - 30 + 'px';
    }
</script>

5.键盘事件对象的属性

以下列举了键盘事件对象中,获取按键的相关属性。

键盘事件对象属性说明
keyCode返回按键的ASCII码值
1.通过事件对象获取用户按下的按键
<script>
    /* 利用keycode返回的ASCII码值来判断用户按下了那个键 */
    document.onkeyup = function(e) {
        console.log('onkeyup:' + e.keyCode); //不区分大小写字母,返回大写字母的ASCII码值。
    }
    document.onkeypress = function(e) {
        console.log('onkeypress:' + e.keyCode); //区分大小写字母,返回大小写字母的ASCII码值。
    }
    document.onkeydown = function(e) {
        console.log('onkeydown:' + e.keyCode); //不区分大小写字母,返回大写字母的ASCII码值。
    }
</script>
2.搜索框获得鼠标焦点案例
<input type="text">
<button type="button">搜索</button><script>
    var input = document.querySelector('input');
    document.onkeyup = function(e) {
        console.log(e.keyCode);
        if (e.keyCode === 81) { //Q键
            input.focus(); // 触发输入框的获得焦点事件
        } else if (e.keyCode === 27) { //Esc键
            input.blur(); // 触发输入框的失去焦点事件
        }
    }
</script>

事件委托

1.什么是事件委托

事件委托就是把事情委托给别人,代为处理。 事件委托说白了就是,不给子元素注册事件,给父元素注册事件,把处理代码在父元素的事件中执行。 事件委托是事件冒泡本身的特性,会带来的坏处,也会带来的好处。 事件委托也称为事件代理,在JQuery 里面称为事件委派。

举个简单的例子:

事件代理’就是把原本需要绑定的事件委托给父元素,让父元素负责事件监听。事件代理的原理是DOM元素的事件冒泡。使用事件代理的好处是可以提高性能

多个事件同时发生,有两种方法,一种是每个人同时执行不同的事情,另一种是将所有的事情分配给他的父元素,委托给父级去办事

2.事件委托的作用

使用事件委托可以节约工作量并提高程序的性能。 比如一个ul下有多个li,现要求点击每个li都弹出对话框, 以前需要给每个li注册事件,相应地就要多次访问DOM,就会延长整个页面的交互就绪时间。 现在我们只要给ul注册事件,从而只需要操作一次 DOM ,这样就大大提高了程序的性能。

3.事件委托的使用

给父元素注册事件,利用事件冒泡,当子元素的事件触发,会冒泡到父元素,然后去控制相应的子元素。 具体如何去控制子元素呢,我们只要使用 e.target,就可以获取到事件源(比如点击的那个子元素),从而就可以对这个子元素进行操作了。

<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.style.backgroundColor = 'green';
    })
</script>

3.JavaScript BOM