Livewire3:组件切换时JS重复加载问题的排查与解决
问题描述
使用Livewire 3开发后台管理系统时,通过侧边栏(<livewire:sidebar />)中带wire:navigate属性的链接切换Livewire组件,网络面板显示所有JS文件(如app.js)都会重复加载,但这些JS仅需在首次加载时运行一次。以下是相关代码结构:
admin\layouts\master.blade.php
<!DOCTYPE html> <html lang="en"> @include('admin.layouts.header-scripts') <body class="hold-transition sidebar-mini"> <div class="wrapper"> @include('admin.layouts.nav') <livewire:sidebar /> {{ $slot }} </div> @include('admin.layouts.footer-scripts') </body> </html>
admin\layouts\header-scripts.blade.php
<head> <meta charset="utf-8"> <meta name="viewport" content="width=device-width, initial-scale=1"> <meta http-equiv="x-ua-compatible" content="ie-edge"> <title> {{ $title ?? 'Home' }} | Admin Panel </title> <link rel="icon" type="image/x-icon" href="https://www.w3schools.com/favicon.ico"> <!-- Font Awesome Icons --> <link rel="stylesheet" href="{{asset('bower_components/admin-lte/plugins/fontawesome-free/css/all.min.css')}}"> <!-- Theme style --> <link rel="stylesheet" href="{{asset('bower_components/admin-lte/dist/css/adminlte.min.css')}}"> <link rel="stylesheet" href="{{asset('bower_components/admin-lte/plugins/datatables-bs4/css/dataTables.bootstrap4.min.css')}}"> <link rel="stylesheet" href="{{asset('bower_components/admin-lte/plugins/datatables-responsive/css/responsive.bootstrap4.min.css')}}"> <link rel="stylesheet" href="{{asset('bower_components/admin-lte/dist/css/adminlte.min.css')}}"> <link rel="stylesheet" href="{{asset('bower_components/admin-lte/plugins/summernote/summernote-bs4.css')}}"> <!-- Google Font: Source Sans Pro --> <link href="https://fonts.googleapis.com/css?family=Source+Sans+Pro:300,400,400i,700" rel="stylesheet"> @yield('styles') @livewireStyles </head>
admin\layouts\footer-scripts.blade.php
<script src="{{asset('js/app.js')}}"></script> <!-- Bootstrap 4 --> <script src="{{ asset('bower_components/admin-lte/plugins/bootstrap/js/bootstrap.bundle.min.js') }}"></script> <!-- AdminLTE App --> <script src="{{ asset('bower_components/admin-lte/dist/js/adminlte.min.js') }}"></script> @yield('js') @livewireScripts
views\livewire\sidebar.blade.php
<aside class="main-sidebar sidebar-dark-primary elevation-4"> <div class="sidebar"> <nav class="mt-2"> <ul class="nav nav-pills nav-sidebar flex-column" data-widget="treeview" role="menu" data-accordion="false"> <li class="nav-item"> <a href="/home" wire:navigate class="nav-link {{ request()->is('home') ? 'active' : '' }}"> <i class="nav-icon fas fa-home"></i> Dashboard </a> </li> <li class="nav-item"> <a href="/getAbout" wire:navigate class="nav-link {{ request()->is('getAbout*') ? 'active' : '' }}"> <i class="nav-icon fas fa-cog"></i> About Us </a> </li> </ul> </nav> </div> </aside>
web.php
Route::get('/home', HomeIndex::class); Route::get('/getAbout', AboutIndex::class);
app\Http\Livewire\HomeIndex.php
<?php namespace App\Http\Livewire; use Livewire\Attributes\Title; use Livewire\Component; class HomeIndex extends Component { #[Title('Home')] public $title = 'Dashboards'; public function render() { return view('livewire.home-index'); } }
views\livewire\home-index.blade.php
<div class="content-wrapper"> Home Index page </div>
getAbout对应的Livewire内容与上述类似。
解决方案
<head>中的脚本仅会加载一次,但<body>中的脚本会在每次页面切换时重新执行——这是因为Livewire使用wire:navigate切换页面时,会替换<body>的全部内容,新页面中的所有<script>标签都会被执行:
<!-- 页面一 --> <body> <script> console.log('在页面一执行') </script> </body> <!-- 页面二 --> <body> <script> console.log('在页面二执行') </script> </body>
如果希望<body>中的某个<script>标签仅在首次页面访问时运行,只需为其添加data-navigate-once属性,Livewire就只会在初始加载时执行它:
<script data-navigate-once src="{{asset('js/app.js')}}"></script> <script data-navigate-once src="{{ asset('bower_components/admin-lte/plugins/bootstrap/js/bootstrap.bundle.min.js') }}"></script> <script data-navigate-once src="{{ asset('bower_components/admin-lte/dist/js/adminlte.min.js') }}"></script>
修改你的footer-scripts.blade.php文件,给所有需要仅加载一次的脚本标签加上data-navigate-once属性,即可解决重复加载问题。
内容的提问来源于Stack Exchange,提问作者Shiva Kunwar
相关产品推荐
相关产品推荐

