Livewire3中点击wire:navigate后JS失效及标识符重复问题
问题场景
在Livewire 3的全页组件app布局中,添加了侧边栏开合的JavaScript代码,初始运行正常。但点击带有wire:navigate属性的链接后,页面自定义JS失效,且控制台报错:Identifier 'adminHamburger' has already been declared at swapCurrentPageWithNewHtml。
相关代码如下:
自定义侧边栏JS代码
const adminHamburger = document.querySelector('#admin-hamburger'); const sidebar = document.querySelector('aside'); adminHamburger.addEventListener('click', function() { sidebar.classList.toggle('translate-x-64'); });
布局代码
<!DOCTYPE html> <html lang="{{ str_replace('_', '-', app()->getLocale()) }}" dir="rtl"> <head> <meta charset="utf-8"> <meta name="viewport" content="width=device-width, initial-scale=1"> <meta name="csrf-token" content="{{ csrf_token() }}"> <title>{{ config('app.name', 'Laravel') }}</title> <!-- Fonts --> <link rel="preconnect" href="https://fonts.bunny.net"> <link href="https://fonts.bunny.net/css?family=figtree:400,500,600&display=swap" rel="stylesheet" /> <!-- Scripts --> @vite(['resources/css/app.css', 'resources/js/app.js']) </head> <body class="font-sans antialiased"> <div class="min-h-screen"> @include('layouts.back.header') @include('layouts.back.sidebar') <!-- Page Content --> <main> {{ $slot }} </main> @include('layouts.back.footer') <script> const adminHamburger = document.querySelector('#admin-hamburger'); const sidebar = document.querySelector('aside'); adminHamburger.addEventListener('click', function() { sidebar.classList.toggle('translate-x-64'); }); </script> </div> </body> </html>
路由配置
Route::get('/admin', App\Livewire\Back\Index::class);
问题原因
Livewire的wire:navigate采用AJAX局部替换页面内容的方式实现无刷新跳转,不会重新加载整个页面:
- 原布局中的
<script>会在每次页面替换后再次执行,const声明的全局变量会因重复定义抛出错误; - 旧页面中的DOM元素被替换后,原绑定的事件监听失效,新元素未重新绑定监听,导致JS功能失效。
解决方案
方案1:使用事件委托(推荐)
将事件监听绑定到全局document上,通过判断点击目标实现功能,避免元素替换后监听失效,同时避免全局变量重复声明问题:
替换布局中的<script>代码为:
document.addEventListener('click', function(e) { if (e.target.id === 'admin-hamburger') { const sidebar = document.querySelector('aside'); sidebar.classList.toggle('translate-x-64'); } });
方案2:利用Livewire livewire:navigated事件
在每次wire:navigate跳转完成后,重新获取元素并绑定监听,同时处理变量重复声明问题:
替换布局中的<script>代码为:
document.addEventListener('livewire:navigated', function() { // 使用let避免重复声明错误 let adminHamburger = document.querySelector('#admin-hamburger'); const sidebar = document.querySelector('aside'); // 克隆元素清除旧监听,避免重复绑定 adminHamburger.replaceWith(adminHamburger.cloneNode(true)); adminHamburger = document.querySelector('#admin-hamburger'); adminHamburger.addEventListener('click', function() { sidebar.classList.toggle('translate-x-64'); }); });
方案3:将代码移至app.js并使用Livewire钩子
将JS代码放到resources/js/app.js中,利用Livewire的初始化钩子:
document.addEventListener('livewire:initialized', function() { // 绑定navigated事件 document.addEventListener('livewire:navigated', function() { const adminHamburger = document.querySelector('#admin-hamburger'); const sidebar = document.querySelector('aside'); adminHamburger.addEventListener('click', function() { sidebar.classList.toggle('translate-x-64'); }); }); });
内容的提问来源于stack exchange,提问作者Esmail
相关产品推荐
相关产品推荐

