JS篇 ------ Web API 2

本文详细介绍了JavaScript中的事件绑定,包括通用事件绑定、事件冒泡、事件代理等概念,并通过实例展示了如何使用这些机制。同时,文章探讨了如何通过事件代理减少代码冗余和内存占用,以及在无限滚动图片加载场景下的应用。此外,还提供了一个通用的事件监听函数`binEvent`,并解释了其工作原理。
摘要由CSDN通过智能技术生成

事件&储存

对应知识点

1、通用事件绑定

	<button id="btn1">这是一个按钮</button>
    <div id="div1">
    	<a href="xxxxx" id="link1">这是个a标签</a>
        <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>
        // 通用事件绑定
        var btn = document.getElementById('btn1')
        btn.addEventListener('click', function (event) {
            console.log('clicked')
        })

        // 封装通用事件绑定函数
        function binEvent(elem, type, fn) {
            elem.addEventListener(type, fn)
        }

        // 使用封装的 binEvent
        var a = document.getElementById('link1')
        binEvent(a, 'click', function (e) {
            e.preventDefault() // 阻止默认行为
            alert('clicked')
        })

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>
        // 事件冒泡
        // 封装通用事件绑定函数
        function binEvent(elem, type, fn) {
            elem.addEventListener(type, fn)
        }
        /* 
        解析: div1 中的p2 至 p4 以及 div2 中的 p5 至 p6 都是取消,
        所以可以把取消事件冒泡至 body 上, 只有p1 是激活,所有对p1单独触发事件
        但是p1 也会向上冒泡,div1没有绑定事件,就会冒泡到body
        body绑定了事件,当p1事件触发完了,会接着触发body上的事件
        即 触发‘激活’之后,就会触发‘取消’
        */
        var p1 = document.getElementById('p1')
        var body = document.body
        binEvent(p1, 'click', function (e) {
            console.log(e)
            e.stopPropagation() // 阻止冒泡    
            alert('激活')
        })
        binEvent(body, 'click', function (e) {
            alert('取消')
        })

3、代理

代理:该代理是指冒泡代理

    <div id="div3">
        <a href="#">a1</a>
        <a href="#">a2</a>
        <a href="#">a3</a>
        <a href="#">a4</a>
        <!-- 会随时新增更多的 a 标签 -->
    </div>
        // 代理 该代理是指冒泡代理
        /*
        解析: 给多个标签绑定同一事件时,
        可以通过冒泡到共同父级元素绑定该事件,
        这样的好处是不用一个一个绑定
        减少代码冗余
        减少浏览器内存占用
        */
        var div3 = document.getElementById('div3')
        div3.addEventListener('click', function (e) {
            var target = e.target // 确切当前点击的是哪个标签
            if (target.nodeName === 'A') {
                alert(target.innerHTML)
            }
        })

4、完善通用绑定事件函数 ------ 使用代理和不使用代理的情况

	<p id="p1">激活</p>
    <div id="div1">
        <a href="#">a1</a>
        <a href="#">a2</a>
        <a href="#">a3</a>
        <a href="#">a4</a>
        <!-- 会随时新增更多的 a 标签 -->
    </div>
        // 完善通用绑定事件的函数
        function binEvent(elem, type, selector, fn) {
            if (fn == null) {
                fn = selector
                selector = null
            }
            elem.addEventListener(type, function (e) {
                var target
                if (selector) {
                    target = e.target
                    if (target.matches(selector)) { // 判断传进来的元素是否是当前点击的元素
                        // 使用代理
                        fn.call(target, e)  // 改变 this指向,this指向当前点击的元素上
                    }
                } else {
                // 不使用代理
                    fn(e)
                }
            })
        }

        // 使用代理
        // div1 代理了 a 标签的绑定事件
        var div1 = document.getElementById('div1')
        binEvent(div1, 'click', 'a', function (e) {
            console.log(this.innerHTML) // call 改变的 this this指向了a元素
        })

        // 不使用代理
        var p = document.getElementById('p1')
        binEvent(p, 'click', function (e) {
            console.log(p.innerHTML)
        })

对应面试题

1、编写一个通用的事件监听函数

        function binEvent(elem, type, selector, fn) {
            if (fn == null) {
                fn = selector
                selector = null
            }
            elem.addEventListener(type, function (e) {
                var target
                if (selector) {
                    target = e.target
                    if (target.matches(selector)) { // 判断传进来的元素是否是当前点击的元素
                        // 使用代理
                        fn.call(target, e)  // 改变 this指向,this指向当前点击的元素上
                    }
                } else {
                // 不使用代理
                    fn(e)
                }
            })
        }

2、描述事件冒泡流程

(1)DOM树形结构
(2)事件冒泡
(3)阻止冒泡
(4)冒泡应用(代理,即绑定同一事件时,可以冒泡至共同父级绑定事件)

3、对于一个无限下拉加载图片的页面,如何给每个图片绑定事件

(1)使用代理 (即绑定同一事件时,可以冒泡至共同父级绑定事件)
(2)代理的两个优点
—> 减少代码冗余,使代码简洁
—> 减少浏览器内存占用

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值