美文网首页
40 DOM事件与事件委托

40 DOM事件与事件委托

作者: 卢卢2020 | 来源:发表于2021-01-29 15:03 被阅读0次

    1 捕获和冒泡

    2002年,W3C发布标准

    文档名为DOM Level 2 Events Specification

    规定浏览器应该同时支持两种调用顺序

    首先按 爷爷 => 爸爸 => 儿子 顺序看有没有函数监听

    然后按 儿子 => 爸爸 => 爷爷 顺序看有没有函数监听

    有监听函数就调用,并提供事件信息,没有就跳过

    事件绑定API

    IE5 *:baba.attachEvent('onclick',fn) //冒泡

    网景:baba.addEventListener('click',fn) //捕获

    W3C:baba.addEventListener('click',fn,boolean)   ==>>>> W3C标准

    如果boolean不传值或者为falsy

    就让fn走冒泡,即当浏览器在冒泡阶段发现baba 有fn监听函数,就会调用fn ,并提供事件信息

    如果boolean为true

    就让fn走捕获,即当前浏览器在捕获阶段发现baba有fn监听函数,就会调用fn,并提供事件信息

    术语

    从外向内找监听函数,叫事件捕获

    从内向外找监听函数,叫事件冒泡   

    实例链接  => 先捕获  后冒泡

    2  target VS currentTarget

    e.target - 用户操作的元素

    e.currentTarget - 程序员监听的元素

    this 是e.currentTarget,不推荐使用(因为用this你不知道你获取的是target 还是currentTarget )  =>>>>  在事件监听中 不推荐使用this

    举个例子

    div > span{文字}   当用户点击文字 =>>>>看下面理解

    e.target就是span

    e.currentTarget就是div

    一个特例

    背景

    只有一个div被监听(不考虑父子同时被监听)

    fn分别在捕获阶段和冒泡阶段监听click事件

    用户点击的元素就是开发者监听的

    代码

    div.addEventLisenter('click',f1)   两行中 谁放在前面一行(第一行)谁就先执行 (也就是谁先监听谁先执行)

    div.addEventLisenter('click',fn,true)

    请问,f1先执行还是f2先执行? =>>>>>>>>>   谁先监听谁先执行

    如果把两行调换位置后,请问哪个先执行? =>>>>>>>>  谁先监听谁先执行

    3 取消冒泡  

        =>>捕获不可取消,但冒泡可以

    e.stopPropagetion() 可中断冒泡,浏览器不再向上走

    一般用于封装某些独立的组件

    4 不可阻止默认动作

        有些事件不能阻止默认动作

    MDN 搜索srcoll event,看到Bubbles 和 Cancelable

    Bubbles的意思是该事件是否冒泡,所有冒泡都可取消

    Cancelable的意思是开发者是否可以阻止默认事件

    Cancelable与冒泡无关

    推荐看mnd英文版 中文版本内容不全

    5 如何阻止滚动

    scroll事件不可阻止默认动作

    阻止scroll默认动作没用,因先有滚动才有滚动事件

    要阻止滚动,可阻止wheel和touchstart的默认动作

    注意你需要找准滚动条所有的元素

    但是滚动条还能用,可用css让滚动条width:0

    2 --来自几人谷教学图

    css也行

    使用overflow:hidden可以直接取消滚动条

    但此时JS依然可以修改scrollTop

    6 自定义事件

    各种默认事件链接

    以下代码是如何自定义一个事件

    const button = document.querySelector('.button1')

    button.addEventListener('click',()=>{    

    const event = new CustomEvent('lulu',{        

    detail{name:'frank',age:'18'},        //设置内容

    bubbles:true , //是否取消冒泡        

    composed:false //是否阻止冒泡 不阻止

    })    

    div1.dispatchEvent(event)})div.addEventListener('lulu',(e)=>{     

    //div1为div标签id=div1

    console.log(e.detail)

    })

    自定义事件

    7 事件委托

    事件委托:我委托一个人 帮我干本来我该干的事情

         ====>>>>> 小记 案例用到的一些方法

    1  js字母大小写转换方法

            转换成大写:toUpperCase()

            转换成小写:toLowerCase()

    2  tagName  获取标签名

        e.target.tagName  获取用户点击的标签名

        e.currentTarget.tagName  获取程序员点击事件的标签名

    3 e.target.dataset.id   具体可看下图1

          获取html内容 data-id='1' 里面的1 <div data-id='1'>21313</div>

    4 e.target.textContent 

        获取当前用户操作标签点击按钮的内容21313 <div data-id='1'>21313</div>

    图1

    第一小节 100个按钮 怎么省内存监听

    实例代码

    box.addEventListener('click',(e)=>{   

        const t = e.target    // console.log(t)    

        if(t.tagName.toLowerCase() === 'button'){      

            console.log('button被点击了,我的内容是:'+ t.textContent)    //获取button上面展示的内容 如下图2

            console.log('被点击了 ,我获取的内容是 标签上的data-id= ' + t.dataset.id) //图3图解

         }      

     })    

    事件委托 图2 事件委托图3

    第二小节 怎么监听暂时不存在(后面动态生成或者是setTimeout(1000s)执行)的元素

    上代码

    // 获取暂时不存在的元素

    setTimeout(()=>{    

    const button= document.createElement('button')   

     button.textContent = '我是button内容'    

    // console.log(button)        

    box.appendChild(button) //注意点 写的时候写错了 前面是父元素 后面是要添加的子元素

    },1000)

    box.addEventListener('click',(e)=>{    

    const t = e.target    

    if(t.tagName.toLowerCase()==='button'){             

    console.log('被点击')    

    }})   

    第三小节 封装事件委托

    要求:

    写出这样一个函数on('click','#testDiv','li',fn)

    当用户点击#testDiv里面的li远不时,调用fn函数

    要求用到事件委托

    代码

    setTimeout(()=>{   

     const button = document.createElement('button')    

    button.textContent = '我是动态1000s后button里面的内容'    

    box.appendChild(button)},1000)

    on('click','#box','button',()=>{    

    console.log('元素被点击了')})

    function on(eventType,element,selector,fn){   

     if(!(element instanceof Element)){ //   判断一个元素是不是真正的元素 判断它是不是对象也可以用它  instanceof Object   判断数组 instanof Array

    element = document.querySelector(element)   

     }    

    element.addEventListener(eventType,(e)=>{     

    const t = e.target       

     if(t.matches(selector)){     //matches 判断它是不是一个选择器

           fn(e)       

     }        

     } 

    )}        

    封装委托事件图解

    代码二:高级版 (给button里面的span加点击 代码一 不能实现点击)

    setTimeout(()=>{    

    const button = document.createElement('button')    

    const span = document.createElement('span')    

    span.textContent = '我是动态1000s后span里面的内容'    

    box.appendChild(button)   

     button.appendChild(span)},1000)

    on('click','#box','button',()=>{     

    console.log('button 被点击了')})

    function on(eventType,element,selector,fn){    

    if(!(element instanceof Element)){            

     element = document.querySelector(element)    }    

    element.addEventListener(eventType,(e)=>{       

     let t = e.target        

    while(!t.matches(selector)){            

    if(element === t){             

    t = null               

    break            

    }             

    t = t.parentNode               

     }       

     t && fn.call(t,e,t)   

     })    

     return element      

    }     

    JS支持事件吗?

    答:

    支持 也不支持   以上案例写的DOM事件不属于JS功能,术语浏览器提供的DOM功能

    JS只是调用了DOM提供的addEventListener()而已

    相关文章

      网友评论

          本文标题:40 DOM事件与事件委托

          本文链接:https://www.haomeiwen.com/subject/rkmttltx.html