Bootstrap 5下拉事件在Vue.js 3项目中触发异常问题
Bootstrap 5下拉事件在Vue 3中仅初始化触发的问题解决
我发现Bootstrap 5的下拉事件在Vue.js 3应用中表现异常:应用内的下拉组件功能正常,但show.bs.dropdown/shown.bs.dropdown/hide.bs.dropdown/hidden.bs.dropdown事件仅在应用渲染时触发一次,切换或关闭下拉时完全不响应。而Vue应用外的原生JS版本下拉组件,事件则能按预期触发。
原代码对比
Vue 3应用内的HTML(有问题的写法)
<main> <div class="dropdown" id="dropdown1" v-on="{ 'show.bs.dropdown': console.log('1'),'shown.bs.dropdown': console.log('2'),'hide.bs.dropdown': console.log('3'),'hidden.bs.dropdown': console.log('4') }"> <button id="localeButton" class="btn btn-lg" type="button" data-bs-toggle="dropdown"> <span>X</span> </button> <div class="dropdown-menu dropdown-menu-end" aria-labelledby="localeButton"> <a class="dropdown-item" @click="a('A')">A</a> <a class="dropdown-item" @click="a('B')">B</a> <a class="dropdown-item" @click="a('C')">C</a> <a class="dropdown-item" @click="a('D')">D</a> </div> </div> </main>
Vue 3应用代码
import { createApp } from 'vue' createApp({ data() { return { foo: 'X' } }, methods: { a(n) { this.foo = n } } }).mount('main')
原生JS版本(正常工作)
HTML部分
<div class="dropdown" id="dropdown2"> <button id="button2" class="btn btn-lg" type="button" data-bs-toggle="dropdown"> <span>Y</span> </button> <div class="dropdown-menu dropdown-menu-end" aria-labelledby="button2"> <a class="dropdown-item">Q</a> <a class="dropdown-item">W</a> <a class="dropdown-item">E</a> <a class="dropdown-item">R</a> </div> </div>
JS部分
['show', 'shown', 'hide', 'hidden'].forEach(m => { document.getElementById('dropdown2').addEventListener(m + '.bs.dropdown', event => { console.log(m) }) })
问题原因
核心问题是Vue的v-on事件绑定语法错误:
直接写'show.bs.dropdown': console.log('1')时,console.log('1')会在Vue渲染模板时立即执行,而不是作为事件回调函数等待事件触发。此时绑定给事件的是console.log的返回值(undefined),所以后续事件触发时没有可执行的回调。
而原生JS中,我们传递的是一个箭头函数event => console.log(m),这个函数会在事件触发时才执行,所以能正常响应。
修复方案
把Vue事件绑定改成函数引用或箭头函数,确保回调在事件触发时才执行。
修复后的Vue模板(箭头函数写法)
<main> <div class="dropdown" id="dropdown1" v-on="{ 'show.bs.dropdown': () => console.log('1'), 'shown.bs.dropdown': () => console.log('2'), 'hide.bs.dropdown': () => console.log('3'), 'hidden.bs.dropdown': () => console.log('4') }"> <button id="localeButton" class="btn btn-lg" type="button" data-bs-toggle="dropdown"> <span>{{ foo }}</span> </button> <div class="dropdown-menu dropdown-menu-end" aria-labelledby="localeButton"> <a class="dropdown-item" @click="a('A')">A</a> <a class="dropdown-item" @click="a('B')">B</a> <a class="dropdown-item" @click="a('C')">C</a> <a class="dropdown-item" @click="a('D')">D</a> </div> </div> </main>
或者提取到methods中(更易维护)
修改Vue应用代码
import { createApp } from 'vue' createApp({ data() { return { foo: 'X' } }, methods: { a(n) { this.foo = n }, handleDropdownShow() { console.log('1') }, handleDropdownShown() { console.log('2') }, handleDropdownHide() { console.log('3') }, handleDropdownHidden() { console.log('4') } } }).mount('main')
对应模板
<main> <div class="dropdown" id="dropdown1" v-on="{ 'show.bs.dropdown': handleDropdownShow, 'shown.bs.dropdown': handleDropdownShown, 'hide.bs.dropdown': handleDropdownHide, 'hidden.bs.dropdown': handleDropdownHidden }"> <!-- 其余内容不变 --> </div> </main>
验证效果
修复后,点击下拉按钮展开/收起时,控制台会依次输出对应的日志,和原生JS版本的行为一致。
内容的提问来源于stack exchange,提问作者Linus Yip
相关产品推荐
相关产品推荐

