写在前面
- 冒泡这个问题非常基础,本以为对此已经足够了解,没想到一个不慎还是在实际开发中踩了冒泡的坑。
- 所以掌握好基础非常重要。
注:该笔记中示例是一个vue+vant+nuxt项目。
知识点
事件冒泡:基于dom树形结构,事件会顺着触发元素向上冒泡。当子元素触发事件,事件会依次往上级传递,每一级都可以感知到事件,直到传递到根元素。
简单的示例:
<div id="app">
<div class="father" @click="myConsole('father')">
<div class="son" @click="myConsole('son')">
son
</div>
</div>
</div>
点击son的时候,会先后打印出:son, father。
实战中遇到的问题
点击关闭弹框的按钮,弹框反复闪烁(关闭-打卡-关闭-打开……),关闭不了。
页面示例:
问题代码:
<template>
<!-- 打开微信扫码的按钮 -->
<div class="wechat-button" @click="showQRCodeDialog">
<img class="wechat-button-logo" src="./img/logo.png" alt="logo">
<span class="wechat-button-text">打开微信扫码</span>
<img class="wechat-button-more" src="./img/icon_more.png" alt="more">
<!-- 弹框 -->
<WechatQRCodeDialog :visible.sync="QRCodeDialogShow" />
</div>
</template>
分析原因
第一步,点击按钮触发showQRCodeDialog
事件,出现弹框。
第二步,点击弹框上的关闭按钮,本应该是关闭弹框的,但是因为弹框放在了按钮里面,showQRCodeDialog
事件相当于也绑在弹框上。
归根结底是因为事件冒泡——点击弹框的时候,点击事件穿透到了button上面。触发了showQRCodeDialog
。
扫描二维码关注公众号,回复:
15180186 查看本文章
注意,默认情况下,vant 的弹框就是插入到我们写的位置的,不像element的弹框是插入到body的。
当时一下子还没想到冒泡上去。因为当时一直在做后台管理系统,用的element,很久没用vant的dialog了,下意识以为dialog是在button外面的。
所以有些坑真的是很基础的东西造成的。这说明基础的东西真的不容忽视。
解决方法
方案1:Dialog外面加一个@click.stop 阻止冒泡。
<template>
<div class="wechat-QRCode-dialog-box" @click.stop>
<van-dialog
v-model="show"
class="wechat-QRCode-dialog"
title="微信搜一搜"
cancel-button-text="关闭"
cancel-button-color="#333"
:show-confirm-button="false"
:show-cancel-button="true"
:close-on-click-overlay="true"
>
<img class="wechat-QRCode-img" src="./img/wechat-search.png" alt="微信搜一搜">
<div class="official-account-name">
<span>互联网医院</span>
<span class="official-account-name-button" @click="copyName">复制</span>
</div>
</van-dialog>
</div>
</template>
方案2:改变一下button组件的结构:
<template>
<div class="wechat-button-box">
<div class="wechat-button" @click="showQRCodeDialog">
<img class="wechat-button-logo" src="./img/logo.png" alt="logo">
<span class="wechat-button-text">打开微信扫码</span>
<img class="wechat-button-more" src="./img/icon_more.png" alt="more">
</div>
<WechatQRCodeDialog :visible.sync="QRCodeDialogShow" />
</div>
</template>
不要偷懒,再在外面套一个div就好啦,不要把弹框放在按钮里面。那天正好偷了个懒,于是就踩了个小坑。
知识点补充
事件冒泡的应用场景:
- 事件代理。