JavaScript——DOM 高级事件

注册事件(绑定事件)

1.1 注册事件

给元素添加事件,称为注册事件或者绑定事件
注册事件有两种方式:传统方式和方法监听注册方式

传统注册方式

■ 利用on开头的事件

■ btn.onclick = function() {}
■ 特点:注册事件的唯一性
■ 同一个元素同一个事件只能设置一个处理函数,最后注册的处理函数会覆盖之前注册的处理函数

方法监听注册方式

■ W3C标准 (推荐)
■ addEventListener() 是一个方法
■ IE9之前不支持,可使用attachEvent() 代替
■ 特点:同一个元素同一个事件可以注册多个监听器
■ 按注册事件顺序执行

1.2 addEventListener 事件监听方式

eventTarget.addEventListener(type,listener[,useCapture])
eventTarget.addEventListener()方法将指定的监听器注册到eventTarget(目标对象)中,当对该对象触发指定的事件时,就会执行事件处理函数
该方法接受三个参数:
type:事件类型字符串,比如click、mouseover,不能带on
listener:事件处理函数,事件发生时,会调用该监听函数
useCapture:可选参数,是一个布尔值,默认是false。学完DOM事件流后,我们在进一步学习

1.3 attachEvent 事件监听方式

eventTarget.attachEvent(eventNameWithOn,callback)
eventTarget.attachEvent() 方法将指定的监听器注册到eventTarget(目标对象)中,当该对象触发指定的事件时,就会执行事件处理函数
eventNameWithOn:事件类型字符串,比如:onclick、onmouseover,这里要带on
callback:事件处理函数,当目标触发事件时回调函数被调用

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Document</title>
</head>
<body>
    <button>传统注册事件</button>
    <button>方法监听注册事件</button>
    <button>ie9 attachEvent</button>
    <script>
        var btns = document.querySelectorAll('button');
        btns[0].onclick = function() {
            alert('1');
        } 
        btns[0].onclick = function() {
            alert('2');       //点击第一个按钮弹出 2
        }
        // 支持ie9以上
        btns[1].addEventListener('click',function() {
            alert('3');     //点击第二个按钮,第一次弹出3
        })
        btns[1].addEventListener('click',function() {
            alert('4');    //第二次弹出4
        })
        //支持ie9以下
        btns[2].attachEvent('onclick',function() {
            alert('5');     // ie9以上不支持
        })

    </script>
</body>
</html>

1.4 注册事件兼容性解决方案

在这里插入图片描述

删除事件(解绑事件)

2.1 传统注册方式

eventTarge.onclick = null

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Document</title>
    <style>
        div {
            width: 50px;
            height: 50px;
            background-color: pink;
            margin: 10px;
        }
    </style>
</head>
<body>
    <div>1</div>
    <div>2</div>
    <div>3</div>
    <script>
        var divs = document.querySelectorAll('div');
        divs[0].onclick = function() {
            alert(11);
            // 传统方式删除事件
            divs[0].onclick = null;
        }
        // divs[1].addEventListener('click',function(){
        //     alert(22);
        // })
        divs[1].addEventListener('click',fn);
        function fn() {
            alert(22);
            divs[1].removeEventListener('click',fn);   // 点击一次后,移除事件
        }
    </script>
</body>
</html>

图片点击一次后不会再响应
在这里插入图片描述

2.2删除事件兼容性问题解决方案

在这里插入图片描述

DOM事件流

事件流描述的是从页面中接收事件的顺序
事件发生时会在元素节点之间按照待定的顺序传播,这个传播过程即DOM事件流

DOM事件流分为3个阶段:
1.捕获阶段
2. 当前目标阶段
3. 冒泡阶段
■ 事件冒泡: 事件开始由最具体的元素接收,然后逐级向上传播到DOM最顶层节点的过程
■ 事件捕获: 由DOM最顶层节点开始,然后逐级向下传播到最具体的元素接收的过程

注意:
1 . JS代码中只能执行捕获或者冒泡其中一个阶段.
2. onclick和attachEvent 只能得到冒泡阶段
3. addEventListener(type,listener[,useCapture]) 第三个参数是true, 表示在事件捕获阶段. 如果第三个参数是false或不填, 表示在事件冒泡阶段.
4. 有些事件没有冒泡, 比如 onblur,onfocus, onmouseleave, onmouseenter

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Document</title>
</head>
<body>
    <div class="father">
        <div class="son"></div>
    </div>
    <script>
        // 如果第三个参数是true,那么处于捕获阶段。顺序为:document->html->body->father->son
        // 如果第三个参数是false或不填,那么处于冒泡阶段.顺序为: son->father->body->html->document
        var son = document.querySelector('.son');
        son.addEventListener('click',function() {
            alert('son');
        },true);

        var father = document.querySelector('.father');
        father.addEventListener('click',function() {
            alert('father');
        },true);
    </script>
</body>
</html>

在这里插入图片描述
点击div第一次出现的是father,可知捕获阶段是逐级向下传播的
在这里插入图片描述

事件对象

4.1 事件对象简述

        1.event 就是一个事件对象
        2.先创建事件才能有事件对象,他是系统自动创建的,不需要我们传递参数
        3.事件对象是我们事件的一系列相关数据的集合,跟事件相关的,比如鼠标点击就包含了鼠标的相关信息
        如果是键盘事件,就包含与键盘有关的信息
        4.事件对象可以自己命名
        eventTarget.onclick = function(event) {}
        eventTarget.addEventListener = function(event) {}

官方解释: event对象代表事件的状态,比如按键的状态,鼠标的位置,鼠标按钮的状态
简单解释: 事件发生后,跟事件相关的一系列信息数据的集合都放到这个对象中,他有很多属性和方法

比如:
1.谁绑定了这个事件
2.鼠标触发事件的话,会得到鼠标的相关信息,如鼠标位置
3.键盘触发事件的话,会得到键盘的相关信息,如按了哪个键

4.2 事件对象常见的属性和方法

事件对象属性方法说明
e.target返回触发事件的对象 标准
e,srcElement返回触发事件的对象 非标准 ie678
e.type返回事件的类型 如click mouseover 不带on
e.stopPropagation()该属性阻止冒泡 标准
e.cancelBubble该属性阻止冒泡 非标准
e.returnValue该属性阻止默认事件(默认行为) 比如不让链接跳转 非标准
e.preventDefault()该属性阻止默认事件(默认行为) 比如不让链接跳转 标准

返回触发事件

e.target 返回触发事件的对象
this 返回绑定事件的对象

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Document</title>
    <style>
        div {
            width: 200px;
            height: 100px;
            background-color: pink;
        }
        li {
            width: 100px;
            height: 30px;
            line-height: 30px;
            text-align: center;
            list-style: none;
            background-color: pink;
            border: 1px solid #999;
        }
    </style>
</head>
<body>
    <div>123</div>
    <ul>
        <li>abc</li>
        <li>abc</li>
        <li>abc</li>
    </ul>
    <script>
        var div = document.querySelector('div');
        div.addEventListener('click',function(e) {
            // e.target 返回的是触发事件的对象
            console.log(e.target);
            console.log(this);  // this返回的是绑定事件的对象
        })
        var ul = document.querySelector('ul');
        ul.addEventListener('click',function(e) {
            console.log(this);
            console.log(e.target);
        })
    </script>
</body>
</html>

在这里插入图片描述
在这里插入图片描述
兼容性问题

        div.onclick = function() {
            e = e || window.event;
            var target = e.target || e.srcElement;
            console.log(target);
        }

阻止事件冒泡

5.1 阻止事件冒泡的两种方式

事件冒泡: 开始时由最具体的元素查收,然后逐级向上传播到DOM最顶层节点
事件冒泡本身特性, 有好有坏

e.stopPropagation() 标准
e.cancelBubble = true; 非标准 取消冒泡

事件委托(代理 委派)

点击每个li都会弹出对话框,之前需要给每个li绑定事件,DOM访问的次数越多,会延长整个页面的交互就绪时间

    <ul>
        <li>知否和大娘子</li>
        <li>知否和大娘子</li>
        <li>知否和大娘子</li>
        <li>知否和大娘子</li>
        <li>知否和大娘子</li>
    </ul>

解决以上问题,我们可以用事件委托
事件委托也称事件代理,在jQuery中称为事件委派

事件委托的原理(重)

不是每个子节点单独设置事件监听器,而是事件监听器设置在其父节点上,然后利用其冒泡原理影响设置每个子节点

上面的案例,我们用事件委托: 给ul注册点击事件,然后利用事件对象的target来找到当前点击的li,因为点击li, 事件会冒泡到ul上, ul有注册事件,就会触发事件监听器.
事件委托的作用: 只需做一次DOM操作,提高了程序的性能,减少整个页面的交互就绪时间.

常用的鼠标事件

7.1 鼠标事件

鼠标事件触发事件
onclick鼠标点击左键触发
onmouseover鼠标经过触发
onmouseout鼠标离开触发
onfocus获得鼠标焦点触发
onblur失去鼠标焦点触发
onmousemove鼠标移动触发
onmouseup鼠标弹起触发
onmousedown鼠标按下触发

禁止鼠标右键菜单和禁止选中文字

contextmenu 主要控制应该何时显示上下文菜单,主要用于程序员取消默认的上下文菜单
selectstart 主要禁止选中文字
用e.preventDefault禁止对象的行为

<body>
    <div>1111111</div>
    <script>
        var div = document.querySelector('div');
        // 1.禁用右键菜单
        div.addEventListener('contextmenu',function(e){
            e.preventDefault();
        })
        // 2.禁止鼠标选中
        div.addEventListener('selectstart',function(e) {
            // 阻止这个对象的行为
            e.preventDefault()
        })
    </script>
</body>

7.2 鼠标对象事件

event代表事件的状态,跟事件相关的一系列信息的集合.
现阶段主要使用鼠标事件对象MouseEvent 和键盘事件对象 KeyboardEvent.

鼠标事件对象说明
e.clientX返回鼠标相对于浏览器窗口可视区的X坐标
e.clientY返回鼠标相对于浏览器窗口可视区的Y坐标
e.pageX返回鼠标相对于文档页面的X坐标 IE9+ 支持
e.pageY返回鼠标相对于文档页面的Y坐标 IE9+ 支持
e.screenX返回鼠标相对于电脑屏幕的X坐标
e.screenY返回鼠标相对于电脑屏幕的Y坐标
<!DOCTYPE html>
<html lang="en">

<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Document</title>
    <style>
        body {
            height: 3000px;
        }
    </style>
</head>

<body>
    <script>
        document.addEventListener('click', function (e) {
            // 不管页面是否往下拖动,坐标都相对于当前界面可视区
            console.log('相对于当前页面可视区,X:' + e.clientX + ',Y:' + e.clientY);
            // 返回相对于文档页面的坐标,页面往下拖动,页面可视区同一位置的坐标不同
            console.log('相对于文档页面,X:' + e.pageX + ',Y:' + e.pageY);
            // 返回页面相对于电脑屏幕的坐标
            console.log('相对于电脑屏幕,X:' + e.screenX + ',Y:' + e.screenY);

        })
    </script>
</body>

</html>

在这里插入图片描述

跟随鼠标的天使案例

核心原理: 每次鼠标移动我们都会获得新的坐标,把x值和y值当作图片的left和top值就可移动图片

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Document</title>
    <style>
        img {
            position: absolute;
        }
    </style>
</head>
<body>
    <img src="/images/angel.gif" alt="">
<script>
    var pic = document.querySelector('img');
    document.addEventListener('mousemove',function(e) {
        // 图片要移动距离,并且不占位置,需用绝对定位
        // 每次移动都要获取当前位置
        var x = e.pageX;
        var y = e.pageY;
        pic.style.left = x - 50 + 'px';
        pic.style.top = y - 40 + 'px';
    })
</script>    
</body>

</html>

在这里插入图片描述

常用的键盘事件

鼠标事件触发事件
onkeyup某个键盘按键被松开时触发 不区分大小写
onkeydown某个键盘按键被按下时触发 不区分大小写
onkeypress某个键盘按键被按下时触发 区分大小写 但他不识别功能键, 如shift , crtl, 箭头等
    <script>
        // document.onkeyup = function() {
        //     console.log('按键松开');
        // }
        // document.onkeydown = function() {
        //     console.log('按键按下');
        // }
        // document.onkeypress = function() {
        //     console.log('按键按下,功能键无法识别');
            
        // }
        document.addEventListener('keyup',function() {
            console.log('按键松开');
        })
        document.addEventListener('keydown',function() {
            console.log('按键按下');
        })
        document.addEventListener('keypress',function() {
            console.log('按键按下,功能键无法识别');
        })
    </script>

在这里插入图片描述

8.1 判断用户按下哪个键

e.keyCode 返回该键的ASCII值
ASCII表
在这里插入图片描述

    <script>
        document.addEventListener('keydown', function (e) {
            console.log('down:' + e.keyCode);
        })
        document.addEventListener('keypress', function (e) {
            console.log('press:' + e.keyCode);
        })
    </script>

按下a, b, c 三个键
在这里插入图片描述

模拟京东按键输入内容

点击s键,直接跳到输入框

<body>
    <input type="text">
    <!-- 当我们按下s键,光标就定位到搜索框 -->
    <script>
        var input = document.querySelector('input');
        document.addEventListener('keyup',function(e) {
            // 如果是s键
            if ( e.keyCode === 83) {
                input.focus();
            }else {
                alert('不是s键');
            }
        })
    </script>
</body>

在这里插入图片描述

模拟京东快递单号查询

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

<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Document</title>
    <style>
        * {
            margin: 0;
            padding: 0;
        }

        .search {
            position: relative;
            width: 178px;
            margin: 100px;
        }

        .con {
            display: none;
            position: absolute;
            top: -40px;
            width: 171px;
            border: 1px solid rgba(0, 0, 0, .2);
            box-shadow: 0 2px 4px rgba(0, 0, 0, .2);
            padding: 5px 0;
            font-size: 18px;
            line-height: 20px;
            color: #333;
        }

        .con::before {
            content: '';
            width: 0;
            height: 0;
            position: absolute;
            top: 28px;
            left: 18px;
            border: 8px solid #000;
            border-style: solid dashed dashed;
            border-color: #fff transparent transparent;
        }
    </style>
</head>

<body>
    <div class="search">
        <div class="con">123</div>
        <input type="text" value="请输入您的快递单号" class="jd">
    </div>

    <script>
        // 1.快递单号输入内容,上面的大号字体盒子(con)显示(这里面的字号更大)
        // 2.表单检测用户输入:给表单添加键盘事件
        // 3.把快递单号里面的值(value)获取过来赋值给con盒子(innerText)作为内容
        var search = document.querySelector('.search');
        var con = document.querySelector('.con');
        var text = document.querySelector('.jd');
        text.addEventListener('keyup', function () {
            // 点击文本框,con会显示,并且内容与文本框相同
            if (this.value == '') {
                con.style.display = 'none';
            } else {
                con.style.display = 'block';
                con.innerHTML = this.value;
            }
        })
        // 当失去焦点时,con隐藏
        text.addEventListener('blur', function () {
            con.style.display = 'none';
        })
        text.addEventListener('click', function () {
            if (this.value == '') {
                con.style.display = 'block';
            }
        })
    </script>
</body>

</html>

在这里插入图片描述

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值