升级Livewire至v3后Fullcalendar报错:无法读取events属性
Livewire 3.0 结合 FullCalendar 报错:Cannot read properties of undefined (reading 'events')
升级Livewire从"livewire/livewire": "^2.6"到"livewire/livewire": "^3.0"后,控制台出现以下错误:
"Cannot read properties of undefined (reading 'events')"
错误栈信息:
calendar:1423 Uncaught TypeError: Cannot read properties of undefined (reading 'events') at HTMLDocument.<anonymous> (calendar:1423:70) at dispatch (livewire.js?id=2f6e5d4d:316:8) at Object.start2 [as start] (livewire.js?id=2f6e5d4d:6693:5) at HTMLDocument.<anonymous> (livewire.js?id=2f6e5d4d:7695:17)
我的Livewire组件代码
<?php namespace App\Livewire; use Livewire\Component; use App\Models\Workflow\Orders; use Illuminate\Support\Facades\DB; class Calendar extends Component { public $events = ''; public function render() { $events =Orders::select('id', 'code AS title', 'validity_date AS start', 'statu AS color', DB::raw("1 as url")) ->get() ->map(function ($order) { $order->color = str_replace('2', "#ffc107", $order->color); $order->color = str_replace('3', "#28a745", $order->color); $order->url = route('orders.show', $order->id); return $order; }); $this->events = json_encode($events); return view('livewire.calendar'); } }
视图代码
<div> <div> <div id="calendar-container" wire:ignore> <div id="calendar"></div> </div> </div> </div> @section('js') <script src='https://cdn.jsdelivr.net/npm/fullcalendar@6.1.9/index.global.min.js'></script> <script> document.addEventListener('livewire:init', function () { var data = @this.events; const Calendar = FullCalendar.Calendar; const calendarEl = document.getElementById('calendar'); const calendar = new Calendar(calendarEl, { events: JSON.parse(data), eventColor: '#378006', height: 800, themeSystem: 'bootstrap', headerToolbar: { left: 'prev,next today', center: 'title', right: 'dayGridMonth,timeGridWeek,timeGridDay,listWeek' }, locale: '{{ config('app.locale') }}', }); calendar.render(); }); </script> <link href='https://cdn.jsdelivr.net/npm/bootstrap@4.5.0/dist/css/bootstrap.css' rel='stylesheet'> <link href='https://cdn.jsdelivr.net/npm/@fortawesome/fontawesome-free@5.13.1/css/all.css' rel='stylesheet'> @stop
已尝试操作
- 按Livewire迁移文档要求,将
livewire:load事件替换为livewire:init,问题未解决。
调试思路与解决方案
调试思路
- 确认
@this初始化时机:Livewire 3中livewire:init是最早的初始化事件,此时组件实例可能未完全挂载,导致无法读取events属性。 - 验证
$events数据有效性:检查json_encode($events)生成的内容是否为合法JSON,避免JSON.parse解析失败。 - 排查组件数据传递逻辑:确认组件的
$events属性是否在前端渲染时已完成赋值。
解决方案
方案1:替换为livewire:initialized事件
livewire:initialized事件触发时机晚于livewire:init,此时组件实例已完全挂载:
document.addEventListener('livewire:initialized', function () { var data = @this.events; const Calendar = FullCalendar.Calendar; const calendarEl = document.getElementById('calendar'); const calendar = new Calendar(calendarEl, { events: JSON.parse(data), // 剩余配置不变 }); calendar.render(); });
方案2:直接通过Blade传递数据
取消组件中$events的公共属性赋值,直接将数据传递到视图,绕过Livewire前端实例依赖:
- 修改Livewire组件:
public function render() { $events = Orders::select('id', 'code AS title', 'validity_date AS start', 'statu AS color') ->get() ->map(function ($order) { $order->color = str_replace('2', "#ffc107", $order->color); $order->color = str_replace('3', "#28a745", $order->color); $order->url = route('orders.show', $order->id); return $order; }); return view('livewire.calendar', compact('events')); }
- 修改视图JS部分:
document.addEventListener('livewire:init', function () { // 直接使用Blade变量,无需JSON.parse var data = {!! json_encode($events) !!}; const Calendar = FullCalendar.Calendar; const calendarEl = document.getElementById('calendar'); const calendar = new Calendar(calendarEl, { events: data, // 剩余配置不变 }); calendar.render(); });
方案3:通过Livewire事件传递数据
组件挂载完成后主动向前端发送事件,传递日历数据:
- 修改Livewire组件:
public function mount() { $events = Orders::select('id', 'code AS title', 'validity_date AS start', 'statu AS color') ->get() ->map(function ($order) { $order->color = str_replace('2', "#ffc107", $order->color); $order->color = str_replace('3', "#28a745", $order->color); $order->url = route('orders.show', $order->id); return $order; }); $this->dispatch('calendarEventsLoaded', events: $events); }
- 修改视图JS:
document.addEventListener('livewire:init', function () { const Calendar = FullCalendar.Calendar; const calendarEl = document.getElementById('calendar'); const calendar = new Calendar(calendarEl, { events: [], // 剩余配置不变 }); calendar.render(); // 监听组件发送的事件,更新日历数据 Livewire.on('calendarEventsLoaded', function(data) { calendar.removeAllEvents(); calendar.addEventSource(data.events); }); });
内容的提问来源于stack exchange,提问作者Billyboy35
相关产品推荐
相关产品推荐

