You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Laravel Livewire集成TinyMCE 编辑更新始终指向首条记录异常

问题根因

这是Livewire嵌套组件搭配第三方富文本编辑器时的典型叠加bug,三个问题共同导致异常:

  • 所有编辑器textarea用了固定id editor,TinyMCE默认只会绑定页面第一个同id的DOM节点,不管打开哪个卡片的编辑器,输入事件实际触发的永远是第一个初始化的编辑器实例,请求自然落到第一个组件上。
  • modal-details和template-editor两个组件写在了@foreach循环外面,不在卡片的作用域内,不管点击哪个卡片,传入这两个组件的$template永远是父作用域里的固定变量,不会随点击的卡片切换。
  • 组件PHP代码存在逻辑隐患:一是mount里的非空判断运算符优先级错误,二是updated钩子全局监听所有属性更新,没有指定监听content字段,容易出现非预期触发。
修复方案

按顺序修改即可解决问题:

  1. 调整组件作用域
    把模态框、编辑器组件移到@foreach循环内部,和卡片组件同级,保证每个卡片对应独立的模态框、编辑器实例,每个实例绑定自己的模板数据,wire:key要和每条记录的唯一ID绑定,不能复用。
    改完的模板代码:
@livewire('settings.templates.main')
@foreach($scheduled as $message)
   <livewire:settings.templates.scheduled-task-card :message="$message" wire:key="{{$message->id. '-card' }}">
   {{-- 模态框和编辑器移到循环内,每个卡片绑定自己的模板数据 --}}
   <livewire:settings.templates.modal-details :template="$message->template" wire:key="{{$message->id. '-modal'}}">
   <livewire:settings.templates.template-editor :template="$message->template" wire:key="{{$message->id.'-editor'}}">
@endforeach
  1. 修复DOM id冲突
    把textarea上写死的固定id改成和模板ID绑定的动态值,保证页面上每个编辑器的DOM id全局唯一,避免TinyMCE绑定错节点。
    改完的编辑器视图代码:
{{-- id拼接模板ID,保证全局唯一 --}}
<textarea id="editor-{{$template->id}}" wire:model.lazy="content" class="mt-3 w-full" wire:key="{{$template->id . '-editor-content'}}">
</textarea>
<div wire:loading class="ml-2">
    <svg role="status" class="inline w-6 h-6 mr-2 text-gray-200 animate-spin dark:text-gray-600 fill-indigo-600" viewBox="0 0 100 101" fill="none" xmlns="http://www.w3.org/2000/svg">
    </svg>
</div>

对应的TinyMCE初始化代码也要改成匹配当前动态id的textarea,不要全局查找id为editor的节点。

  1. 修复组件PHP逻辑
    修正判断条件的优先级问题,单独监听content字段的更新,不要用全局updated钩子,同时单独存模板ID避免Livewire后续请求时状态丢失。
    改完的组件类代码:
class TemplateEditor extends Component
{
    public $content;
    public $template;
    public $templateId;

    public function mount($template){
        $this->template = $template;
        $this->templateId = $template->id;
        // 用is_null判断,避免运算符优先级导致的判断错误
        if(!is_null($this->template->body)){
            $this->content = $this->template->body;
        }
    }

    // 只监听content字段的更新,避免其他属性变更时触发不必要的保存
    public function updatedContent(){
        $this->template->body = $this->content;
        $this->template->save();
    }

    public function render()
    {
        return view('livewire.tenant.settings.templates.template-editor');
    }
}
  1. 可选优化(避免后续踩坑)
    给TinyMCE的外层容器加上wire:ignore.self,避免Livewire更新DOM时销毁编辑器实例;如果lazy绑定同步有问题,可以去掉wire:model.lazy,在TinyMCE的change、input事件回调里主动调用Livewire的$wire.set('content', 编辑器内容)方法同步数据,稳定性更高。

改完之后执行php artisan view:clear清除视图缓存,再测试就会发现每个编辑器的更新都会正确写入对应ID的模板记录,不会再固定修改第一条数据。

内容的提问来源于stack exchange,提问作者Gianmarco

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.09.02 06:54:26