Laravel Livewire组件重渲染后JavaScript数据未刷新问题
Livewire重渲染时FullCalendar数据不同步问题修复
问题根因
出现该问题是两个核心逻辑错误导致的:
- 放在
@push('scripts')块内的JS代码只会在页面首次加载时执行一次,后续Livewire组件重渲染不会重新运行这部分代码,所以块内写死的@js($events)永远是第一次渲染时的初始旧值,不会随$events更新。 - 每次触发
contentChanged事件都重新初始化FullCalendar实例,会导致实例重复创建、内存泄漏,也无法正确更新已渲染日历的数据。
修复步骤
1. 修改后端事件派发逻辑
派发浏览器事件时直接把最新的事件数据放到事件载荷里,不要依赖前端模板静态渲染变量:
// 组件类render方法内 $this->dispatchBrowserEvent('contentChanged', [ 'events' => $this->events ]);
2. 重构前端JS逻辑
把日历初始化和数据更新逻辑拆开,只在页面加载完成时初始化一次日历实例,收到更新事件时直接替换日历数据源即可,修改后的模板代码如下:
<div> {{ dump($events) }} <x-card class="mt-4"> <div id='calendar'></div> </x-card> @push('scripts') <script src='https://cdn.jsdelivr.net/npm/fullcalendar@5.11.0/main.min.js'></script> <script src='https://cdn.jsdelivr.net/npm/fullcalendar@5.11.0/locales/de.js'></script> <link href='https://cdn.jsdelivr.net/npm/fullcalendar@5.11.0/main.min.css' rel='stylesheet' /> <script> // 存储全局日历实例,避免重复初始化 let calendar = null; // 页面首次加载完成后初始化日历 document.addEventListener('DOMContentLoaded', () => { const calendarEl = document.getElementById('calendar'); calendar = new FullCalendar.Calendar(calendarEl, { locale: "de", events: [], // 初始空数据,后续动态更新 headerToolbar: { left: 'prev,next today', center: 'title', right: 'dayGridMonth,timeGridWeek,timeGridDay,listWeek' }, loading: function(isLoading) { if (!isLoading) { this.getEvents().forEach(e => { if (e.source === null) e.remove(); }); } }, }); calendar.render(); }); // 监听后端数据更新事件 document.addEventListener('contentChanged', (e) => { // 直接从事件载荷获取最新数据,无需依赖@js静态渲染 const formattedEvents = e.detail.events.map(event => ({ ...event, backgroundColor: event.title < 3 ? '#B23220' : (event.title < 11 ? '#C3B031' : '#20B22C'), borderColor: event.title < 3 ? '#B23220' : (event.title < 11 ? '#C3B031' : '#20B22C'), })); // 替换日历数据源 calendar.removeAllEvents(); calendar.addEventSource(formattedEvents); }); // 原有刷新逻辑可保留 @this.on('refreshCalendar', () => { calendar.refetchEvents(); }); </script> @endpush </div>
注意事项
不要在
@push('scripts')、@vite这类提前加载的脚本块内,通过Blade指令直接绑定Livewire的动态变量。这类块内的代码不会随Livewire重渲染重新执行,绑定的变量永远是首次页面加载的静态值。动态数据必须通过事件载荷传递,或者调用Livewire前端API主动获取。
内容的提问来源于stack exchange,提问作者PeterPan
相关产品推荐
相关产品推荐

