JavaScript核心之DOM系列(二)

事件基础

JavaScript有能力创建动态页面,而事件是可以被JavaScript侦测到的行为。网页中的每个元素都可以产生某些可以触发 JavaScript 函数的事件,比如点击事件。

事件由三部分组成:

①事件源:事件被触发的对象(比如被点击的按钮

②事件类型:如何触发的(什么事件)。比如点击、鼠标经过、键盘按下

③事件处理程序:事件触发后,做什么操作。采取函数赋值的方式

事件的执行步骤:获取事件源→注册事件→添加事件处理程序

常见的鼠标事件:

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

键盘事件:

onkeydown
按键被按下时触发 通过keycode属性获取相应键的ASCII码值,keyup和keydown事件不区分大小写,a和A都是65
onkeyup 按键被松开时触发
onkeypress 按键被按下时触发(不能识别功能键,eg:Ctrl、shift、箭头等) 通过keycode属性获取相应键的ASCII码值,keypress事件 区分字母大小写(A65  a97)

 

执行顺序  keydown->keypress->keyup

 注册事件

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

注册事件的两种方式:传统方式和方法监听注册方式

传统方式 方法监听方式
利用on开头的事件,如onclick 符合w3c标准(推荐),使用addEventListener()方法
btn.onclick=function(){} btn.addEventListener('click',function(){})
特点:注册事件的唯一性 特点:同一个元素同一个事件可以注册多个监听器(监听处理函数)
同一个元素同一个事件只能设置一个处理函数 按注册顺序依次执行
后注册的处理函数会覆盖前面注册的处理函数 注:IE9前不支持,可使用attachEvent()代替

传统方式的注册事件:

    <button id="btn">唐伯虎</button>
    <script>
        // 点击按钮 弹出对话框
        // 1.获取事件源
        var btn=document.getElementById('btn');
        // 2.事件类型 点击(onclick)
        // 3.事件处理程序 通过一个函数赋值的方式
        btn.onclick=function(){
            console.log(btn.innerText);            
            alert('点秋香')
        }
    </script>
addEventListener方法监听方式:
 语法:eventTarget.addEventListener(type,listener[,useCapture])

type:监听事件类型字符串,比如:click、mousemove,注意这里不要带on

listener:事件处理函数。事件发生时,会调用该监听函数

useCapture:可选参数。Boolean,设为true时,沿着DOM树向上冒泡的事件,不会触发listener。默认为false

<button>方法监听注册方式</button>
<script>
  var btn=document.querySelector('button');
  btn.addEventListener('click',function(){
            alert("11");
  });
</script>

注册事件兼容性解决方案

<script>
    function addEventListener(element,eventName,fn){
            if(element.addEventListener){
                element.addEventListener(eventName,fn);
            }else if(element.attachEvent){
                element.attachEvent('on'+eventName,fn);
            }else{
                element['on'+eventName]=fn;
            }
     }
<script>

兼容性处理原则:先照顾大多数浏览器,再处理特殊浏览器

删除事件(解绑事件)

传统方式注册的事件解绑 方法监听注册方式解绑
eventTarget.onclick=null eventTarget.removeEventListener(type,listener[,useCapture])

DOM事件流

事件发生时,会在元素节点之间按照特定的顺序传播,这个传播过程即DOM事件流

DOM事件流分为3个阶段:捕获阶段、当前目标阶段、冒泡阶段

eg:div的点击事件

事件冒泡:事件开始由最具体的元素接受,然后逐层向上传播到DOM最顶节点的过程 (IE最早提出)

事件捕获:由DOM最顶节点开始,逐层向下传播到最具体的元素接收过程 (网景最早提出)

捕获阶段 冒泡阶段
    <style>
        .father{
            width: 300px;
            height: 300px;
            background-color: green;   
        }
        .son{
            width: 150px;
            height: 150px;
            background-color: yellowgreen;
            margin: 0 auto;
        }
    </style>
<div class="father">
   <div class="son">son盒子</div>
</div> 
<script>        
        // js 代码中只能执行捕获或者冒泡其中一个阶段
        // onclick和attachEvent(ie)只能得到冒泡阶段
        // 捕获阶段 如果addEventListener
        // 第三个参数为true,处于捕获阶段 执行顺序document ->html->body->father->son
        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>

 

    <style>
        .father2{
            width: 300px;
            height: 300px;
            background-color: green;          
        }
        .son2{
            width: 150px;
            height: 150px;
            background-color: yellowgreen;
            margin: 0 auto;
        }
    </style>
<div class="father2">
     <div class="son2">son2盒子</div>
</div> 
<script>
        // 冒泡阶段 如果addEventListener第三个参数为false(不写 默认是false)
        // ,处于冒泡阶段 son2->father2->body->html->document
        var son=document.querySelector('.son2')
        son.addEventListener('click',function(){
            alert('son2') // 先出
        })
        var father=document.querySelector('.father2')
        father.addEventListener('click',function(){
            alert('father2') // 后出
        })
        // var father=document.querySelector('.father')
        document.addEventListener('click',function(){
            alert('document') // 最后出
        })

</script>

 

实际开发中,很少使用事件捕获,更关注的是事件冒泡。

注:有些事件没有冒泡,比如:onblur\onfocus\onmouseenter\onmouseleave

事件对象

事件对象是事件的一系列相关数据的集合

比如:鼠标触发事件,得到鼠标的相关信息(如 鼠标的位置)

           键盘触发事件,得到键盘的相关信息(如 按了哪个键)

看下面代码:

<div></div>
    <script>
        // 事件对象
        var div=document.querySelector('div');
        div.onclick=function(event){
            console.log(event);// 普通浏览器
            console.log(window.event); // ie6-8            
            console.log(event||window.event);// 兼容性写法            
        }
    </script>

上面代码中,event就是一个事件对象。有了事件才会有事件对象,是系统自动创建的,无需传参。

这个事件对象可以自己命名,一般为event、evt、e等等。

注:事件对象也有兼容性问题 ie678 通过window.event获取

事件对象的常见属性方法

e.target 返回触发事件的对象 标准
e.srcElement 返回触发事件的对象 非标准 ie6-8
e.type 返回事件类型(如click、mouseover) 不带on
e.cancelBubble 阻止冒泡 非标准 ie6-8
e.returnValue 阻止默认事件(默认行为,比如 不允许a链接跳转) 非标准 ie6-8
e.preventDefault 标准
e.stopPropagation 阻止冒泡 标准

注:e.target与this的区别

e.target返回的是触发事件的对象(元素)

this返回的是绑定事件的对象(元素)

代码如下:

<ul>
        <li>1</li>
        <li>2</li>
        <li>3</li>
        <li>4</li>
    </ul>
    <script>
        var ul=document.querySelector('ul');
        // this指向的是绑定事件的对象 元素
        // e.target指向的触发事件的对象 元素
        ul.addEventListener('click',function(e){
            console.log(this); // 返回<ul><li>……</ul>
            console.log(e.target);  //返回 点击的li <li>2</li>
            
        });
    </script>

阻止默认行为:

<a href="http://www.baidu.com">百度</a>
    <script>
        // 阻止默认行为(事件),让链接不跳转、或者提交按钮不提交
        var a=document.querySelector('a')
        // a.addEventListener('click',function(e){
        //     e.preventDefault()
        // })
        a.onclick=function(e){
            // 普通浏览器 preventDefault()方法
            // e.preventDefault();
            // 低版本浏览器 ie6-8 returnValue属性
            // e.returnValue
            // 也可以用return false 阻止默认行为 没有兼容性问题
            return false
        }
    </script>

阻止事件冒泡

<style>
        .father{
            width: 300px;
            height: 300px;
            background-color: green;
            
        }
        .son{
            width: 150px;
            height: 150px;
            background-color: yellowgreen;
            margin: 0 auto;

        }
    </style>
<div class="father">
        <div class="son">son盒子</div>
    </div>
    <script>
        var son=document.querySelector('.son');
        var father=document.querySelector('.father');
        son.addEventListener('click',function(e){
            alert('son') // 先出
            // 阻止事件冒泡  父级的弹框不生效
            e.stopPropagation()
            // e.cancelBubble=true  // 兼容ie6-8
        });
        father.addEventListener('click',function(){
            alert('father') // 后出
        });
        // var father=document.querySelector('.father')
        document.addEventListener('click',function(){
            alert('document') // 最后出
        });

    </script>

事件委托

利用事件冒泡本身的特性,只指定一个事件处理程序,就可以管理某一类型的所有事件。

就是说,如果我们有许多以类似方式处理的元素,那么就不必为每个元素分配一个处理程序,而是把事件监听器设置在它们的父元素上。

应用场景:当前被点击的li为红色

<ul>
        <li>知否知否1</li>
        <li>知否知否2</li>
        <li>知否知否3</li>
        <li>知否知否4</li>
        <li>知否知否5</li>
    </ul>
    <script>
        var ul = document.querySelector('ul')
        ul.addEventListener('click', function(e) {
            console.log(e.target);
            var li = ul.children
            for (let i = 0; i < li.length; i++) {
                li[i].style.color = ''

            }
            e.target.style.color = 'red'
        })
    </script>

 

posted @ 2021-06-09 09:56  ljy景  阅读(70)  评论(0)    收藏  举报