DOM二级事件

835 阅读6分钟

DOM二级事件

1、什么是事件?

事件分为两部分:

1)行为本身

//1)行为本身:浏览器天生赋予其的行为:onclick、onmouseover(onmouserenter)、onmouseout(onmouseleave)、
// onmousemove、onmousedown、onmouseup、onmousewheel(鼠标滚轮滚动行为)、onscroll(滚动条滚动行为)、
// onresize(window.onresize浏览器窗口大小改变事件)、onload、onunload(浏览器关闭)
// onfocus(文本框获取焦点行为)、onblur(文本框失去焦点行为)、onketdown、onkeyup(键盘按下和抬起行为)...
// ->哪怕没有给上述的行为绑定方法,时间也是存在的,当我们点击这个盒子的时候,同样会触发它的onclick行为,只是
// 什么事情都没做而已
2)事件绑定
//2)事件绑定:给元素的某一个行为绑定方法
//DOM 0级事件绑定
//->把匿名函数定义的部分当做一个赋值给odiv的点击行为(函数表达式)
let odiv = document.getElementById('div1')
odiv.onclick = function(){
   //->当触发odiv的click行为的时候,会把绑定的这个函数执行
}
//->onclick这个行为定义在当前元素的私有属性上



//DOM 2级事件绑定
odiv.addEventListener('click',function(){
    alert(this)
},false)
//->addEventListener这个属性是定义在当前元素所属EventTarget这个类的原型上的

MouseEvent:鼠标事件对象

let odiv = document.getElementById('div1')

//->把匿名函数定义的部分当做一个赋值给odiv的点击行为(函数表达式)
//->当我们触发#div1的点击行为的时候,会执行对应绑定上的方法
//->重要:不仅仅把绑定的方法执行了,而且浏览器还默认的给这个方法传递了一个参数值
//->MouseEvent:鼠标事件对象
//1)它是一个对象数据类型值,里面包含了汗多的属性名和属性值,这些都是用来记录当前鼠标的相关信息的
//2)MouseEvent -->UIEvent -->Event -->Object //原型链
//3)MouseEvent记录的是页面中唯一一个鼠标每一次触发时候的相关信息,和到底是在哪个元素上触发的没有关系

关于事件对象MoiseEvent的兼容问题

//->1)事件对象本身的获取存在兼容问题:标准浏览器中是浏览器给方法传递的参数,我们只需要定义形参e就可以获取到;
//在IE6~8中浏览器不会给方法传递参数,我们如果需要的话,需要到window.event中获取查找
//-> e = e || window.event

odiv.onclick = function(e){
    e = e || window.event
    //->e.type:存储的是当前鼠标触发的行为类型:"click"
    //-> e.clientX/e.clientY:当前鼠标触发点距离当前屏幕左上角的x/y轴的坐标值
    //->e.target:事件源,当前鼠标触发的是哪个元素,那么它存储的就是哪个元素,但是在IE6~8中不存在这
    //个属性(e.target的值是undefined),使用e.srcElement来获取事件源
    e.target = e.target || e.srcElement
    //->e.pageX/e.pageY:当前鼠标触发点距离body左上角(页面第一屏幕最左上端)的x/y轴的坐标,但是ie6~8中没有这个
    //属性,我们通过使用clientY + 滚动卷去的高度来获取也可以
    // e.pageX = e.pageX || (e.clientX + (document.documentElement.scrollLeft || document.body.scrollLeft))
    // e.pageY = e.pageY || (e.clientX + (document.documentElement.scrollTop || document.body.scrollTop))

    //->e.preventDefault:阻止浏览器的默认行为,在ie6~8中没有这个方法,需要使用e.returnValue = false来代替
    // e.preventDefault ? e.preventDefault() : e.returnValue = false;
    //return false //和上述的代码一样的效果,都是在阻止默认的行为

    //->e.stopPropagation:阻止事件的冒泡传播,在ie6~8中不兼容,使用e.cancelBubble = true来代替
    // e.stopPropagation ? e.stopPropagation() : e.cancelBubble = true;


   console.log(e)
}
document.body.onclick = function(e){
    console.log(e.pageX)
    console.log(e.clientX)
}
let input1 = document.getElementById('input1')
input1.onkeyup = function(e){
    // -> KeyboardEvent
    // -> e.keyCode:当前键盘上每一个键对应的值
    
}

事件的默认传播机制

● 捕获阶段:从外向内依次查找元素
● 目标阶段:当前事件源本身的操作
● 冒泡阶段:从内到外依次触发相关行为(最常用的就是冒泡阶段)
注意:使用DOM 0级事件绑定给元素的某一个行为绑定的方法,都是在行为触发后的冒泡阶段把方法执行的

addEventListener参数解释

//addEventListener->第一个参数是行为的类型 第二个参数是给当前的行为绑定的方法 第三个参数是控制在哪个阶段发生
//true:在捕获阶段发生  false 在冒泡阶段发生
document.body.addEventListener('click',function(){
    console.log('body')
},true)

事件委托

● 利用事件的冒泡传播机制(触发当前元素的某个行为,它父级所有元素的相关行为都会被触发),如果一个容器中有很多元素都要绑定点击事件,我们没必要一个个的绑定,只需要给最外层容器绑定一个点击事件即可,在这个方法执行的时候,通过事件源的区分来进行不同的操作

委托函数封装

function binEvent(elem, type, selector, fn) {
    if (fn == null) {
        fn = selector
        selector = null
    }
    elem.addEventListener(type, function (e) {
       
        let target;
        if (selector) {
            //有代理代理
            target = e.target
            console.log(e)
            if(target.matches(selector)){
              
                fn.call(target,e)
            }
        } else {
            //不是代理
            fn(e)
        }
    })
}

DOM0级事件和二级事件的区别

//->使用DOM2级事件绑定,其实是让box通过原型链一直找到EventTarget这个内置类原型上的addEventListener方法实现


//->DOM0级事件绑定:只能给一个元素的某一个行为绑定一次方法,第二次绑定的会把前面的覆盖掉

 let box = document.getElementById('div1')

// box.onclick = function(){
//     console.log("1")
// }
// box.onclick = function(){
//     console.log("2")
// }


//->DOM2:可以给某一个元素的同一个行为绑定多个不同的方法
box.addEventListener('click',function(e){
    console.log('1')
},false)
box.addEventListener('click',function(e){
    console.log('2')
},false)

//->DOM2:DOM0中的行为类型,DOM2一样可以绑定;而且DOM2中还提供了一些DOM0没有的行为类型->
//DOMContentLoaded:当页面中的DOM结构(HTML结构加载完成)触发的行为

document.addEventListener('DOMContentLoaded',function(e){
    console.log('oj8k')
},false)

//2、window.onload = function(){} ->当页面中的所有资源都加载完成(图片、HTML结构、音视频...)才会执行后面的
//函数;并且在一个页面中只能用一次,后面再写会把前面的覆盖掉; ->因为它是采用DOM0事件绑定,所以只能绑定一次

//jQuery:$(document).ready(function(){}) -> $(function(){})
//只要当页面中的HTML结构加载完成就会执行对应的函数;并且在同一个页面中可以出现多次
//->DOM2事件绑定
//->并且绑定的行为是DOM2中新增加的 DOMContentLoaded 事件

// window.addEventListener('load',function(){},false)

/*
//3、DOM2
function fn1(e){
    console.log(this) //this -> box
}
box.addEventListener('click',fn1,false)
//->移除的时候需要保证三个参数:行为、方法、哪个阶段发生 一点都不能差 ->在使用DOM2绑定的时候,一般使用实名函数
box.removeEventListener('click',fn1,false)
*/

// 4、
//->只能给某个元素的同一个行为绑定多个"不同"的方法(如果方法相同了只能留一个)
//->当行为触发,会按照绑定的先后顺序依次把绑定的方法执行
//->执行的方法中的this是当前被绑定事件的元素本身


//->事件池:是用来存储当前元素行为绑定的方法的(浏览器自带的机制)


//->在IE6-8浏览器中,不支持addEventListener,如果想实现DOM2事件绑定只能用attachEvent/detachEvent
box.attachEvent('onclick',fn1) 
//->它只有两个参数,不能像addEventListener那样控制在哪个阶段发生,默认只能在冒泡阶段发生
//->行为需要添加'on'(和DOM0特别类似)
//->可以绑定多个事件
function fn1(e){
    console.log(this) //this -> box
}

BOM一些属性

// navigator.userAgent ->打印浏览器属性

// location
location.protocol  //协议
location.host //域名
location.pathname //路径
location.search //问号后面的参数
location.hash //#后面的参数
location.href //整个url集合