Vue/Nuxt项目中注入的事件监听器切换页面时不触发如何解决?
问题根因
你当前用的是直接给已存在元素绑定事件的逻辑,执行初始化函数时还没渲染到页面的元素,自然不会被加上监听器,下面是两种可行的解决方案:
方案1:修改注入JS为事件委托逻辑(最推荐)
直接将事件绑定到页面已经存在的上层节点(比如document或者你业务中确定不会被销毁的容器),通过事件冒泡匹配目标元素,不管后续什么时候插入的手风琴按钮都能生效,只需要执行一次初始化即可:
function initDeviceGroupCollapses () { // 可替换为你业务中确定存在的上层容器,比如[data-beam-injectes-interactivity]节点,减少无效事件判断 document.addEventListener('click', (event) => { // 匹配点击源最近的手风琴触发按钮 const button = event.target.closest('[data-toggle="collapse"]') if (!button) return event.stopPropagation() const target = button.dataset.target if (!target) return const collapse = document.querySelector(target) if (collapse) { collapse.style.display = collapse.style.display === 'none' ? 'block' : 'none' } }, false) } // 注入后直接执行一次即可,不需要等待目标元素渲染 initDeviceGroupCollapses()
方案2:调整JS注入时机,保证在HTML渲染完成后执行
如果你不想修改原有JS逻辑,调整执行顺序即可:
- 先把API返回的HTML内容插入到页面DOM中
- 再注入执行对应的JS代码
如果是用Vue的v-html渲染返回的HTML,需要配合nextTick等待DOM更新完成再注入JS:
// Vue组件内逻辑示例 axios.get('/your/api').then(res => { const { html, js } = res.data // 先赋值HTML内容 this.renderHtml = html // 等待DOM渲染完成 this.$nextTick(() => { const injectTo = document.querySelector('[data-beam-injectes-interactivity]') const script = document.createElement('script') script.innerHTML = js injectTo.appendChild(script) }) })
如果HTML是分批动态渲染的,可以搭配MutationObserver监听容器的DOM变化,每次节点更新后重新调用一次initDeviceGroupCollapses()即可,不过性能比事件委托方案差。
内容的提问来源于stack exchange,提问作者Ryan H
相关产品推荐
相关产品推荐

