不用事件代理,我终于战胜了事件冒泡

1,257 阅读1分钟

起因:

react + ant Design 表格人名列点击调用outLook的邮件分享将当前选中行的内容分享出去。大致结构如下:
标题人名
邮件分享张三

问题:

如何先选中当前行再触发a标签的onclick事件?

概念:

DOM事件流分为三个阶段:事件捕获,处于目标阶段,事件冒泡。事件捕获和冒泡如下图所示:

bubbling-capturing.png

再看问题:

shareEmail.bmp 点击张三 先触发a标签的onclick事件,再冒泡到div标签触发div的onclick事件。 我们先用事件代理来处理一下问题

<body>
    <div class="userName">
        <a  class="shareEmail">
            张三
        </a>
    </div>
    <div onclick="getMessage()" class="userName">
        <a onclick="handleShareEmail()" class="shareEmail">
            李四
        </a>
    </div>

    <script>
        const divEl = document.getElementsByClassName('userName')[0]
        const aEl = document.getElementsByClassName('shareEmail')[0]
        // addEventListener的第三个参数 true: 事件捕获, false:事件冒泡
        addListener(divEl, 'click', getMessage, true)
        addListener(aEl, 'click',handleShare, true)

        function getMessage() {
            console.log('等我处理完 你再分享')
        }

        function handleShare() {
            console.log('share email!')
        }

        function addListener(el, eventName,fn, isCapture) {
            el.addEventListener(eventName, fn.bind(this), isCapture)
        }
    </script>
</body>

结果符合要求如下:

result01.bmp

现在咱们不用事件代理,引入debounce延时执行来试试:

    const handleShareEmail = debounce(handleShare, 1000)
    function debounce(fn, wait, immediate) {
        let timer = null
        return function () {
           const that = this
           if(timer) clearTimeout(timer)
           timer = setTimeout(() => {
                fn.apply(that)
                timer = null
            }, wait)
        }
    }

fourLi.bmp 成功啦!!

总结:

我们生活中或工作上不要固定思维困住,本文通过延时执行,即达到了目的,也让我对事件循环Event Loop有了进一步的认识,不失为一种解决方案,完结撒花!