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

Laravel Livewire表格首单元格重复渲染组件的原因及解决方法

问题

我在Livewire组件的blade文件中编写了如下代码:

<span class="px-2 py-1 rounded-lg {{ $backgroundColor }} {{ $textColor }}">
    {{ $status->name }}
</span>

随后在表格中这样渲染该组件:

<tbody>
    @foreach($initiatives as $key => $initiative)
        <tr class="justify-center text-center">
            <th class="p-2">{{ $initiative->name }}</th>
            <td class="p-2">{{ $initiative->ease_of_implementation }}</td>
            <td class="p-2">
                <livewire:status-badge :status="$initiative->status"></livewire:status-badge>
            </td>
            <td class="p-2">{{ $initiative->priority->name }}</td>
            <td class="p-2">{{ $initiative->owner_id }}</td>
        </tr>
    @endforeach
</tbody>

现在遇到的问题是:表格里前两个Livewire组件被渲染到第一个<td>中,第二个<td>为空,从第三个组件开始恢复正常。查看HTML发现第一个<td>里有两个该组件。

补充信息
一个Initiative实例内容如下:

App\Models\Initiative {#1502 ▼ // resources\views/livewire/project-span.blade.php
  #connection: "mysql"
  #table: "initiatives"
  #primaryKey: "id"
  #keyType: "int"
  +incrementing: true
  #with: []
  #withCount: []
  +preventsLazyLoading: false
  #perPage: 15
  +exists: true
  +wasRecentlyCreated: false
  #escapeWhenCastingToString: false
  #attributes: array:18 [▼
    "id" => 7
    "name" => "dolores"
    "description" => "Quia et architecto ea. Sed possimus et optio quaerat veniam ratione quibusdam nam. Adipisci at quia nemo voluptas. Fugiat qui natus illum."
    "problem_statement" => "Blanditiis fugiat reiciendis dolor officia beatae voluptas dolorum. Placeat dicta est voluptatibus. Animi earum sit est et cumque eius. Fugit itaque tempore dol ▶"
    "desired_outcome" => "Qui atque esse suscipit odio quo magnam. Ipsa cumque vel omnis totam. Est doloribus optio quia est porro. Quia id qui porro totam."
    "approach_methodology" => "Accusantium ratione eveniet sint eos placeat dolor. Et quia molestias voluptatibus. Vel consectetur ut sequi itaque consectetur et iure sint."
    "target_completion" => "2022-08-01"
    "ease_of_implementation" => 2
    "project_id" => 1
    "owner_id" => 1
    "strategic_objective_id" => 3
    "status_id" => 2
    "priority_id" => 1
    "operating_location_id" => 1
    "site_id" => 1
    "tenant_id" => 1
    "created_at" => "2022-10-27 21:47:09"
    "updated_at" => "2022-10-27 21:47:09"
  ]
  #original: array:18 [▶]
  #changes: []
  #casts: []
  #classCastCache: []
  #attributeCastCache: []
  #dates: []
  #dateFormat: null
  #appends: []
  #dispatchesEvents: []
  #observables: []
  #relations: array:3 [▼
    "owner" => App\Models\User {#1531 ▶}
    "status" => App\Models\Status {#1559 ▼
      #connection: "mysql"
      #table: "statuses"
      #primaryKey: "id"
      #keyType: "int"
      +incrementing: true
      #with: []
      #withCount: []
      +preventsLazyLoading: false
      #perPage: 15
      +exists: true
      +wasRecentlyCreated: false
      #escapeWhenCastingToString: false
      #attributes: array:6 [▼
        "id" => 2
        "name" => "Active"
        "color" => "cyan"
        "tenant_id" => 1
        "created_at" => null
        "updated_at" => null
      ]
      #original: array:6 [▶]
      #changes: []
      #casts: []
      #classCastCache: []
      #attributeCastCache: []
      #dates: []
      #dateFormat: null
      #appends: []
      #dispatchesEvents: []
      #observables: []
      #relations: []
      #touches: []
      +timestamps: true
      #hidden: []
      #visible: []
      #fillable: []
      #guarded: []
    }
    "priority" => App\Models\Priority {#1549 ▶}
  ]
  #touches: []
  +timestamps: true
  #hidden: []
  #visible: []
  #fillable: []
  #guarded: []
}
原因分析

核心问题是循环渲染Livewire组件时缺少唯一标识。Livewire依赖DOM diff算法更新视图,循环中组件没有wire:key的话,算法无法准确区分不同实例,尤其前几个组件状态相似时,会出现DOM匹配错误,导致组件错位、重复渲染。

修复方案

给循环里的<tr>和Livewire组件添加wire:key,用唯一值(比如模型ID)作为标识,确保每个实例都能被准确识别。

修改后的表格代码:

<tbody>
    @foreach($initiatives as $key => $initiative)
        <tr class="justify-center text-center" wire:key="initiative-row-{{ $initiative->id }}">
            <th class="p-2">{{ $initiative->name }}</th>
            <td class="p-2">{{ $initiative->ease_of_implementation }}</td>
            <td class="p-2">
                <livewire:status-badge 
                    :status="$initiative->status"
                    wire:key="status-badge-{{ $initiative->id }}"
                ></livewire:status-badge>
            </td>
            <td class="p-2">{{ $initiative->priority->name }}</td>
            <td class="p-2">{{ $initiative->owner_id }}</td>
        </tr>
    @endforeach
</tbody>
  • 给<tr>加key是为了让Livewire区分每一行
  • 给组件加key确保每个status-badge实例唯一,避免DOM匹配错误

用模型ID作为key比循环$key更可靠,因为$key在分页或数据顺序变化时可能重复,而数据库主键不会有冲突。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.14 19:00:29