• 【面试题】事件绑定和冒泡


    1. 事件绑定

    1.1 addEventListener实现事件绑定

    const btn = document.getElementById('btn1')
    btn.addEventListener('click', event => {
    	console.log('clicked')
    })
    
    • 1
    • 2
    • 3
    • 4

    1.2 手写绑定函数

    // 通用的绑定函数
    function bindEvent(elem, type, fn){
    	elem.addEventListener(type, fn)
    }
    
    const a = document.getElementById('link1')
    
    bindEvent(a, 'click', e=>{
    	e.preventDefault()   // 阻止默认行为
    	alert('clicked')
    })
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11

    1.3 示例

    DOCTYPE html>
    <html lang="en">
    
    <head>
        <meta charset="UTF-8">
        <meta http-equiv="X-UA-Compatible" content="IE=edge">
        <meta name="viewport" content="width=device-width, initial-scale=1.0">
        <title>事件绑定title>
        <style>
            div {
                border: 1px solid #ccc;
                margin: 10px 0;
                padding: 0 10px;
            }
        style>
    head>
    
    <body>
        <button id="btn1">一个按钮button>
    
        <script>
        	// 通用的绑定函数
            function bindEvent(elem, type, fn) {
                elem.addEventListener(type, fn)
            }
    
            const btn1 = document.getElementById('btn1')
    
            bindEvent(btn1, 'click', event =>{
                console.log(event.target)   // 获取触发的元素
                event.preventDefault()   // 阻止默认行为
                alert('clicked')
            })
        script>
    body>
    
    html>
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37

    在这里插入图片描述

    2. 事件冒泡

    <div id="div1">
        <p id="p1">激活p>
        <p id="p2">取消p>
        <p id="p3">取消p>
        <p id="p4">取消p>
    div>
    <div id="div2">
        <p id="p5">取消p>
        <p id="p6">取消p>
    div>
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    <script>
    	// 通用的绑定函数
        function bindEvent(elem, type, fn) {
            elem.addEventListener(type, fn)
        }
    
        const p1 = document.getElementById('p1')
        const body = document.body
        
        bindEvent(p1, 'click', event=>{
            console.log('激活')
        })
    
        bindEvent(body, 'click', event=>{
            console.log('body clicked')
        })
    </script>
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17

    事件冒泡的情况:点击“激活”的p标签,会触发p标签绑定的事件,同时也会触发body绑定的事件。
    请添加图片描述
    此时,我们在“激活”的p标签的绑定事件中加入stopPropagation(),就可以防止事件冒泡。

    <script>
    	// 通用的绑定函数
        function bindEvent(elem, type, fn) {
            elem.addEventListener(type, fn)
        }
    
        const p1 = document.getElementById('p1')
        const body = document.body
        
        bindEvent(p1, 'click', event=>{
        	event.stopPropagation()     // 阻止事件冒泡
            console.log('激活')
        })
    
        bindEvent(body, 'click', event=>{
            console.log('body clicked')
        })
    </script>
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18

    请添加图片描述

    3. 事件代理

    事件代理是利用了事件冒泡的机制完成的。当需要对多个元素绑定相同的事件时,可以将事件绑定在这些元素的父元素上,利用冒泡机制实现子元素的事件绑定。

    事件代理的优点:

    • 代码简洁
    • 减少浏览器内存占用
    DOCTYPE html>
    <html lang="en">
    <head>
        <meta charset="UTF-8">
        <meta http-equiv="X-UA-Compatible" content="IE=edge">
        <meta name="viewport" content="width=device-width, initial-scale=1.0">
        <title>事件代理title>
    head>
    <body>
        <div id="div1">
            <a href="#">a1a><br>
            <a href="#">a2a><br>
            <a href="#">a3a><br>
            <a href="#">a4a><br>   
        div>
    
        <script>
            function bindEvent(elem, type, fn){
                elem.addEventListener(type, fn)
            }
    
            const div1 = document.getElementById('div1')
    
            bindEvent(div1, 'click', event=>{
                event.preventDefault()   // 阻止跳转链接的默认行为
                const target = event.target
                if(target.nodeName === 'A'){
                    alert(target.innerHTML)
                }
            })
        script>
    body>
    html>
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33

    请添加图片描述

    4. 通用的事件绑定函数

    function bindEvent(elem, type, selector, fn){
        if(fn == null){
            fn = selector
            selector = null
        }
        elem.addEventListener(type, event=>{
            const target = event.target
            if(selector){
                // 代理绑定
                if(target.matches(selector)){
                    fn.call(target, event)
                }
            }else{
                // 普通绑定
                fn.call(target, event)
            }
        })
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
  • 相关阅读:
    Ant Design Pro从零到一(认识AntD)
    HTML+CSS+JavaScript仿京东购物商城网站 web前端制作服装购物商城 html电商购物网站
    伽蓝集团进击IPO:原料端价值是国货美妆的新“解药”?
    什么是数据安全性?
    AHB、AXI、APB
    Go语言strings标准库
    STM32点灯大师(点了一颗LED灯,轮询法)
    基于JavaGUI界面和MySQL的商品价格波动交易买卖系统
    Ansible数组同步至Shell脚本数组中
    计算机毕业设计源代码java项目开发实例ssm+mysql实现简单的物流快递管理系统[包运行成功]
  • 原文地址:https://blog.csdn.net/zx1041561837/article/details/128110380