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

Laravel Livewire组件中filterRows方法无法触发求助

问题:Livewire Notifications组件中filterRows方法无法触发

开发基于Laravel的Livewire项目时,Notifications组件的链接点击无法触发filterRows方法,其他Livewire组件正常运行,数据显示正常,但该方法始终不执行。

相关代码片段

Livewire视图代码

<!-- Livewire view code -->
<div>
    <li class="relative" x-data="{ open: false }">
        <button class="relative align-middle rounded-md focus:outline-none focus:shadow-outline-purple"
            @click="open = !open" @keydown.escape="open = false" @click.away="open = false" aria-label="Notifications"
            aria-haspopup="true">
            <svg class="w-5 h-5" aria-hidden="true" fill="currentColor" viewBox="0 0 20 20">
                <path
                    d="M10 2a6 6 0 00-6 6v3.586l-.707.707A1 1 0 004 14h12a1 1 0 00.707-1.707L16 11.586V8a6 6 0 00-6-6zM10 18a3 3 0 01-3-3h6a3 3 0 01-3 3z">
                </path>
            </svg>
            <!-- Notification badge -->
            @if ($notificationsCounts->count() > 0)
                <span aria-hidden="true"
                    class="absolute -top-1 -right-1 inline-flex w-3 h-3   bg-red-600 border-2 border-white rounded-full dark:border-gray-800  text-white animate-pulse">
                </span>
            @endif
        </button>
      
        <template  x-if="open" @keydown.escape="open = false"  @click.away="open = false">
            <ul x-transition:leave="transition ease-in duration-150"          x-transition:leave-start="opacity-100"
                x-transition:leave-end="opacity-0"
                class="absolute right-0 w-56 p-2 mt-2 space-y-2 text-gray-600 bg-white border border-gray-100 rounded-md shadow-md dark:text-gray-300 dark:border-gray-700 dark:bg-gray-700">
               
                @foreach ($notifications as $notification)                   
                    <li class="flex">
                        <a class="inline-flex items-center justify-between w-full px-2 py-1 text-sm font-semibold transition-colors duration-150 rounded-md hover:bg-gray-100 hover:text-gray-800 dark:hover:bg-gray-800 dark:hover:text-gray-200"
                            href="#" {{-- wire:key="'notif'- $notif->id " --}} 
                            wire:key="'{{ 'notif-' . $notification->id }}'"
                            wire:click.prevent="filterRows('{{ $notification->model }}', '{!! $notification->id !!}' )"
                            >
                            <span>{{ class_basename($notification->model) }}</span>
                            <span
                                class="inline-flex items-center justify-center px-2 py-1 text-xs font-bold leading-none text-red-600 bg-red-100 rounded-full dark:text-red-100 dark:bg-red-600">
                                {{ $notification->message }}
                            </span>
                        </a>
                    </li>
                @endforeach
            </ul>
        </template>
    </li>       
</div>

组件嵌入代码

<livewire:notifications />

Livewire组件类代码

<?php  
namespace App\Http\Livewire;

use Illuminate\Support\Facades\DB;
use Livewire\Component;
use App\Models\Notification;
use Illuminate\Support\Facades\Auth;

class Notifications extends Component
{
    public $notifs;
    public $selectedModel;
    public $notificationsCounts;

    public function mount()
    {
        $this->refreshNotifications();
    }

    public function refreshNotifications()
    {
        $this->notificationsCounts = Notification::select('model', DB::raw('COUNT(*) as count'))
            ->where('is_read', 0)
            ->where('user_id', Auth::id())
            ->groupBy('model')
            ->get();
    }

    public function render()
    {
        $this->notifs = Notification::where('is_read', 0)
            ->where('user_id', Auth::id())
            ->get();

        return view('livewire.notifications', [
            'notifications' => $this->notifs,
            'notificationsCounts' => $this->notificationsCounts,
        ]);
    }

    public function filterRows($model, $id)
    {
        $this->selectedModel = $model;

        // Update the is_read field to 1 for the corresponding model
        Notification::where('model', $model)
            ->where('user_id', Auth::id())
            ->update(['is_read' => 1]);

        // Refresh the notifications data
        $this->refreshNotifications();
        
        // Perform any other filtering logic or redirect as needed
    }
}

问题分析与修复

你的视图代码中有两处关键错误导致方法无法触发:

1. wire:key格式错误

当前写法多了一层冗余单引号,生成的key值无效,Livewire无法正确追踪DOM元素:

wire:key="'{{ 'notif-' . $notification->id }}'"

修正为:

wire:key="notif-{{ $notification->id }}"

2. wire:click.prevent参数传递错误

  • 使用{!! $notification->id !!}存在XSS风险且完全没必要,直接用{{ $notification->id }}即可;
  • Livewire支持直接在指令中传递组件变量,无需手动拼接字符串,写法更简洁。

原写法:

wire:click.prevent="filterRows('{{ $notification->model }}', '{!! $notification->id !!}' )"

修正为(二选一即可):

<!-- 写法1:Blade变量拼接 -->
wire:click.prevent="filterRows('{{ $notification->model }}', {{ $notification->id }})"

<!-- 写法2:直接传递Livewire变量(推荐) -->
wire:click.prevent="filterRows($notification->model, $notification->id)"

修正后的完整视图代码片段

<!-- Livewire view code -->
<div>
    <li class="relative" x-data="{ open: false }">
        <button class="relative align-middle rounded-md focus:outline-none focus:shadow-outline-purple"
            @click="open = !open" @keydown.escape="open = false" @click.away="open = false" aria-label="Notifications"
            aria-haspopup="true">
            <svg class="w-5 h-5" aria-hidden="true" fill="currentColor" viewBox="0 0 20 20">
                <path
                    d="M10 2a6 6 0 00-6 6v3.586l-.707.707A1 1 0 004 14h12a1 1 0 00.707-1.707L16 11.586V8a6 6 0 00-6-6zM10 18a3 3 0 01-3-3h6a3 3 0 01-3 3z">
                </path>
            </svg>
            <!-- Notification badge -->
            @if ($notificationsCounts->count() > 0)
                <span aria-hidden="true"
                    class="absolute -top-1 -right-1 inline-flex w-3 h-3   bg-red-600 border-2 border-white rounded-full dark:border-gray-800  text-white animate-pulse">
                </span>
            @endif
        </button>
      
        <template  x-if="open" @keydown.escape="open = false"  @click.away="open = false">
            <ul x-transition:leave="transition ease-in duration-150"          x-transition:leave-start="opacity-100"
                x-transition:leave-end="opacity-0"
                class="absolute right-0 w-56 p-2 mt-2 space-y-2 text-gray-600 bg-white border border-gray-100 rounded-md shadow-md dark:text-gray-300 dark:border-gray-700 dark:bg-gray-700">
               
                @foreach ($notifications as $notification)                   
                    <li class="flex">
                        <a class="inline-flex items-center justify-between w-full px-2 py-1 text-sm font-semibold transition-colors duration-150 rounded-md hover:bg-gray-100 hover:text-gray-800 dark:hover:bg-gray-800 dark:hover:text-gray-200"
                            href="#" 
                            wire:key="notif-{{ $notification->id }}"
                            wire:click.prevent="filterRows($notification->model, $notification->id)"
                            >
                            <span>{{ class_basename($notification->model) }}</span>
                            <span
                                class="inline-flex items-center justify-center px-2 py-1 text-xs font-bold leading-none text-red-600 bg-red-100 rounded-full dark:text-red-100 dark:bg-red-600">
                                {{ $notification->message }}
                            </span>
                        </a>
                    </li>
                @endforeach
            </ul>
        </template>
    </li>       
</div>

额外优化建议

  • 组件类中的$notifs可改为直接在视图中执行查询,或设为计算属性,避免在render方法中重复查询;
  • filterRows方法中批量更新同model的所有通知状态可能不符合业务需求,可改为仅更新当前点击的通知:
    Notification::where('id', $id)
        ->where('user_id', Auth::id())
        ->update(['is_read' => 1]);
    

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.17 02:35:02