Livewire 3模态框重复添加遮罩导致黑屏问题求助
当使用Livewire 3的Navigation功能时,每次导航到包含Bootstrap模态框的页面并打开模态框,背景会逐渐变黑,原因是每次页面导航后,模态框的遮罩层(.modal-backdrop)没有被彻底清理,重复渲染后叠加导致遮罩越来越暗。
以下是几种可行的解决方案:
方案1:组件销毁时清理遮罩层
利用Livewire的生命周期钩子,在组件即将从DOM移除时触发遮罩清理逻辑:
1.1 修改组件类代码
<?php namespace App\Livewire\Admin\PetCodes; use Livewire\Component; class GeneratePetCodes extends Component { public function render() { return view('livewire.admin.pet-codes.generate-pet-codes'); } // 组件即将 dehydrate(从DOM移除)时触发清理事件 public function dehydrate() { $this->dispatch('cleanup-modal-backdrops'); } }
1.2 组件视图添加监听脚本
在组件的Blade视图末尾添加:
<script> document.addEventListener('livewire:init', () => { Livewire.on('cleanup-modal-backdrops', () => { // 移除所有多余的遮罩层 document.querySelectorAll('.modal-backdrop').forEach(backdrop => backdrop.remove()); // 移除body上的modal-open类,避免页面滚动锁定 document.body.classList.remove('modal-open'); }); }); </script>
方案2:用Livewire状态控制模态框(推荐)
放弃原生Bootstrap的data-bs-*属性,改用Livewire的状态管理模态框显示,避免DOM重复渲染问题:
2.1 修改组件类
<?php namespace App\Livewire\Admin\PetCodes; use Livewire\Component; class GeneratePetCodes extends Component { public $showModal = false; public function openModal() { $this->showModal = true; } public function closeModal() { $this->showModal = false; } // 状态变化时通知前端控制模态框 public function updatedShowModal($value) { $this->dispatch('toggle-modal', $value); } public function render() { return view('livewire.admin.pet-codes.generate-pet-codes'); } }
2.2 修改视图代码
<!-- 替换原触发按钮 --> <button type="button" class="btn btn-alt-primary push" wire:click="openModal">Generate Pet Codes</button> <!-- 模态框添加wire:ignore.self避免Livewire重复渲染 --> <div class="modal fade" id="generate-pet-codes" tabindex="-1" aria-labelledby="generate-pet-codes" aria-hidden="true" wire:ignore.self> <div class="modal-dialog" role="document"> <div class="modal-content"> <div class="block block-rounded block-transparent mb-0"> <div class="block-header block-header-default"> <h3 class="block-title">Modal Title</h3> <div class="block-options"> <button type="button" class="btn-block-option" wire:click="closeModal" aria-label="Close"> <i class="fa fa-fw fa-times"></i> </button> </div> </div> <div class="block-content fs-sm"> <x-forms.text-input type="number" placeholder="Amount" name="amount" /> <form wire:submit="generate"> <div class="mt-3"> <x-forms.button title="Generate" /> </div> </form> </div> <div class="block-content block-content-full text-end bg-body"> <button type="button" class="btn btn-sm btn-alt-secondary me-1" wire:click="closeModal">Close</button> </div> </div> </div> </div> </div> <script> document.addEventListener('livewire:init', () => { const modal = new bootstrap.Modal(document.getElementById('generate-pet-codes')); Livewire.on('toggle-modal', (show) => { show ? modal.show() : modal.hide(); }); // 模态框手动关闭时同步Livewire状态 document.getElementById('generate-pet-codes').addEventListener('hidden.bs.modal', () => { Livewire.dispatch('closeModal'); }); }); </script>
方案3:全局导航后清理遮罩
在应用的主布局文件中添加监听,利用Livewire Navigation的livewire:navigated事件,每次导航完成后清理多余遮罩:
<script> document.addEventListener('livewire:navigated', () => { const backdrops = document.querySelectorAll('.modal-backdrop'); // 如果存在多个遮罩,只保留最后一个(如果有模态框正在显示),否则全部移除 if (backdrops.length > 1) { Array.from(backdrops).slice(0, -1).forEach(backdrop => backdrop.remove()); } else if (!document.querySelector('.modal.show')) { backdrops.forEach(backdrop => backdrop.remove()); document.body.classList.remove('modal-open'); } }); </script>
内容的提问来源于stack exchange,提问作者Ethan Patchell
相关产品推荐
相关产品推荐

