Laravel Livewire导航后JavaScript功能失效,仅全页刷新可用的问题求助
我在自己的应用里用Laravel Livewire做导航,默认布局里包含以下结构和脚本:
<div class="flex grow"> <x-layouts.sidebar /> <!-- End of Sidebar --> <!-- Wrapper --> <div class="wrapper flex grow flex-col"> <!-- Header --> <x-layouts.header /> <main class="grow content pt-5" id="content" role="content"> {{ $slot }} </main> <x-layouts.footer /> <!-- End of Footer --> </div> <!-- End of Wrapper --> </div> <script src="v2/assets/js/core.bundle.js"></script> <script src="v2/assets/vendors/apexcharts/apexcharts.min.js"></script> <script src="v2/assets/js/widgets/general.js"></script> <script src="v2/assets/js/layouts/demo1.js"></script>
当我全页刷新的时候,一切都正常——侧边栏切换、下拉菜单这些JavaScript功能都能正常工作。但用Livewire.navigate在组件间导航的时候,JavaScript就失效了。哪怕用Livewire导航回同一个页面,功能也恢复不了,只有全页刷新才能解决。
我尝试过的方法
Livewire事件监听器
我试着用livewire:navigated、livewire:navigating和livewire:navigate事件来重新初始化脚本,代码如下:
<script> document.addEventListener('livewire:navigated', () => { console.log('true working'); @php $scripts = [ public_path('v2/assets/js/core.bundle.js'), public_path('v2/assets/vendors/apexcharts/apexcharts.min.js'), public_path('v2/assets/js/widgets/general.js'), public_path('v2/assets/js/layouts/demo1.js'), ]; foreach ($scripts as $script) { if (file_exists($script)) { echo file_get_contents($script); } else { echo "// File not found: " . basename($script) . "\n"; } } @endphp }); </script>
事件监听器确实触发了,脚本也加载到DOM里了(通过Network标签验证过),但导航之后功能还是不能用。
手动添加脚本
我把一个自定义脚本文件放在webpackUniversalModuleDefinition函数外面,手动引入后,哪怕用Livewire导航也能正常工作。这让我怀疑问题可能和Webpack打包脚本的方式或者语法有关。
我的猜测和观察
Webpack通用模块定义
我的脚本都是用下面这种模式打包的:
(function webpackUniversalModuleDefinition(root, factory) { if (typeof exports === 'object' && typeof module === 'object') module.exports = factory(); else if (typeof define === 'function' && define.amd) define([], factory); else { var a = factory(); for (var i in a) (typeof exports === 'object' ? exports : root)[i] = a[i]; } })(self, function() { // Module code here });
我怀疑这种打包方式就是导航后功能失效的原因,但搞不懂为什么全页刷新的时候又能正常工作。
全局作用域问题
也许打包后的脚本没有把功能暴露到全局作用域(比如window或者self),所以在Livewire的部分DOM更新之后就访问不到了。
导航时的脚本执行
我注意到,如果把逻辑放在Webpack的包裹外面(比如直接放在<script>标签里,或者脚本文件的最底部),导航后就能正常工作。这让我觉得问题出在函数的注册或者初始化方式上。
我想弄明白的问题
- 为什么Webpack打包的脚本在全页刷新时能用,但Livewire导航后就不行?
- 这个问题和Webpack暴露函数或者注册到全局作用域的方式有关吗?
- 有没有什么好办法能让这类脚本在Livewire导航后也能无缝工作?
- 这个问题会不会和缓存、模块初始化或者Livewire的部分DOM更新有关?
我希望侧边栏切换、下拉菜单这些JavaScript功能,在用Livewire.navigate导航到新组件后,能和全页刷新时一样正常工作。
备注:内容来源于stack exchange,提问作者Muhammad Umar

