如何在Laravel Livewire导航跳转时显示Flash消息?
问题场景
使用普通重定向时,Flash消息能正常通过Toastr显示:
$url = route('role.detail', 5); session()->flash('success', config('app.success')); return redirect($url);
但切换为Livewire的navigate重定向后,无论是使用session()->flash()还是直接dispatch事件,Toastr都无法显示消息:
// 尝试1:session flash $url = route('role.detail', 5); session()->flash('success', config('app.success')); return $this->redirect($url, navigate: true); // 尝试2:dispatch事件 $url = route('role.detail', 5); $this->dispatch('success',['message'=>config('app.success')]); return $this->redirect($url, navigate: true);
当前用于显示消息的Toastr代码:
<script> $(document).ready(function(){ toastr.options = { "closeButton": true, "debug": false, "newestOnTop": false, "progressBar": true, "positionClass": "toast-top-right", "preventDuplicates": false, "onclick": null, "showDuration": "300", "hideDuration": "500", "timeOut": "5000", "extendedTimeOut": "1000", "showEasing": "swing", "hideEasing": "linear", "showMethod": "fadeIn", "hideMethod": "fadeOut" }; window.addEventListener('success', event=>{ toastr.remove(); toastr.success(event.detail[0].message); }); window.addEventListener('error', event=>{ toastr.remove(); toastr.error(event.detail[0].message); }); }); @if(Session::has('success')) window.onload = function(){ toastr.remove(); toastr.success("{{session('success')}}"); }; @endif @if(Session::has('error')) window.onload = function(){ toastr.remove(); toastr.error("{{session('error')}}"); }; @endif </script>
原因分析
Livewire的navigate是SPA式页面跳转,不会触发window.onload事件,也不会重新渲染整个页面的Blade模板逻辑,所以原来依赖window.onload和初始Blade渲染的Session检测代码不会执行。同时,直接dispatch事件会在页面跳转前被中断,无法被新页面的监听函数捕获。
解决方案
方案1:结合redirect()->with()与livewire:navigated事件监听
- 修改后端重定向代码,使用
with()传递Flash消息:
$url = route('role.detail', 5); return $this->redirect($url, navigate: true)->with('success', config('app.success'));
- 替换前端Toastr代码,监听Livewire的
livewire:navigated事件(该事件在每次navigate跳转后触发):
<script> document.addEventListener('livewire:navigated', function() { // 配置Toastr选项 toastr.options = { "closeButton": true, "debug": false, "newestOnTop": false, "progressBar": true, "positionClass": "toast-top-right", "preventDuplicates": false, "onclick": null, "showDuration": "300", "hideDuration": "500", "timeOut": "5000", "extendedTimeOut": "1000", "showEasing": "swing", "hideEasing": "linear", "showMethod": "fadeIn", "hideMethod": "fadeOut" }; // 处理Session Flash消息 @if(Session::has('success')) toastr.remove(); toastr.success("{{ session('success') }}"); {{-- 清除Session,避免重复显示 --}} @php Session::forget('success'); @endphp @endif @if(Session::has('error')) toastr.remove(); toastr.error("{{ session('error') }}"); @php Session::forget('error'); @endphp @endif // 处理Livewire事件 window.addEventListener('success', event => { toastr.remove(); toastr.success(event.detail.message); }); window.addEventListener('error', event => { toastr.remove(); toastr.error(event.detail.message); }); }); </script>
方案2:在目标组件中读取Session并Dispatch事件
- 后端重定向代码保持使用
with()传递消息:
$url = route('role.detail', 5); return $this->redirect($url, navigate: true)->with('success', config('app.success'));
- 在目标页面的Livewire组件(如
RoleDetail.php)的mount方法中读取Session并触发事件:
public function mount($id) { if(session()->has('success')) { $this->dispatch('success', message: session('success')); session()->forget('success'); } // 处理error消息同理 if(session()->has('error')) { $this->dispatch('error', message: session('error')); session()->forget('error'); } }
- 前端Toastr代码保留事件监听部分,确保能捕获组件dispatch的事件:
<script> document.addEventListener('DOMContentLoaded', function() { toastr.options = { // 保持原配置不变 "closeButton": true, "debug": false, "newestOnTop": false, "progressBar": true, "positionClass": "toast-top-right", "preventDuplicates": false, "onclick": null, "showDuration": "300", "hideDuration": "500", "timeOut": "5000", "extendedTimeOut": "1000", "showEasing": "swing", "hideEasing": "linear", "showMethod": "fadeIn", "hideMethod": "fadeOut" }; window.addEventListener('success', event => { toastr.remove(); toastr.success(event.detail.message); }); window.addEventListener('error', event => { toastr.remove(); toastr.error(event.detail.message); }); }); </script>
补充说明
- 使用
session()->forget()是为了避免用户刷新页面后重复显示相同的Flash消息。 livewire:navigated事件是Livewire SPA跳转的核心事件,所有页面切换后的初始化逻辑都可以放在这个监听函数中。
内容的提问来源于stack exchange,提问作者HENG Vongkol
相关产品推荐
相关产品推荐

