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

如何在Alpine.js中正确显示Livewire更新值以切换图标

问题

在Blade组件中需根据更新后的值展示对应图标,但调用togglePinned()方法后,尽管后端值已更新,第二个@if语句中的图标无法立即切换。

前端Blade代码

@php
    $isMyTask = $task->assignees->where('id', console_user()->id)->count();
    $task_user = $task->assignees->where('id', auth()->id())->first();
    $read = $task_user?->pivot->read === 1;
    $pinned = $task_user?->pivot->pinned === 1;
@endphp
(.. some code ..)
<div>
    @if ($isMyTask)
        <a href="#"
            x-data="{ pinned: @entangle('pinnedTask') }"
            @click.prevent="$wire.togglePinned(); console.log('pinned', pinned)"
            @pinned-updated.window="if ($event.detail.task_id === {{ $task->id }}) pinned = $event.detail.pinned"
            :key="pinned ? 'unpinned-{{ $task?->id }}' : 'pinned-{{ $task?->id }}'">
            <i :class="pinned ? 'fas fa-fw fa-thumbtack' : 'fal fa-fw fa-thumbtack'" aria-hidden="true"></i>
        </a>
    @endif
    @if ($isMyTask)
        <a href="#" x-tooltip.placement.top.raw="{{ $pinned ? 'Unpin' : 'Pin' }}"
            wire:click="togglePinned" wire:key="{{ $pinned ? 'unpinned' : 'pinned' }}-{{ $task?->id }}">
            <i class="{{ $pinned ? 'fas' : 'fal' }} fa-fw fa-thumbtack" aria-hidden="true"></i>
        </a>{{( 'KEY ID' . $task?->id) . ' ' . ($pinned ? 'pinned' : 'unpinned') }}
    @endif
</div>

后端Livewire代码

public function togglePinned()
{
    if (! $this->task) {
        return;
    }

    $currentPinnedState = $this->task->assignees()->where('users.id', auth()->id())->first()->pivot->pinned;
    $this->task->assignees()->where('users.id', auth()->id())->first()->pivot->update([
        'pinned' => ! $currentPinnedState,
    ]);

    $this->pinnedTask = [
        'task_id' => $this->task->id,
        'pinned' => ! $currentPinnedState,
    ];
    
    $this->emit('taskUpdated');
}

解决方案

核心原因

第二个按钮的$pinned是Blade渲染页面时一次性计算的静态值,Livewire执行togglePinned()后不会自动重新计算这个变量,导致图标和tooltip无法实时更新。而第一个按钮用了Alpine的@entangle绑定Livewire状态,所以能同步变化。

具体修复步骤

  1. 将$pinned改为Livewire组件的公共属性
    在你的Livewire组件类中添加公共属性,替代Blade里的静态计算:

    public $pinned;
    
    public function mount($task)
    {
        $this->task = $task;
        // 初始化pinned状态
        $taskUser = $this->task->assignees->where('id', auth()->id())->first();
        $this->pinned = $taskUser?->pivot->pinned === 1;
    }
    
  2. 更新后端togglePinned()方法,同步$pinned属性
    更新pivot后,直接更新Livewire的$pinned状态,确保前端能实时获取:

    public function togglePinned()
    {
        if (! $this->task) {
            return;
        }
    
        $taskUser = $this->task->assignees()->where('users.id', auth()->id())->first();
        $currentPinnedState = $taskUser->pivot->pinned;
        $newPinnedState = !$currentPinnedState;
    
        $taskUser->pivot->update(['pinned' => $newPinnedState]);
        
        // 同步Livewire属性
        $this->pinned = $newPinnedState;
        $this->pinnedTask = [
            'task_id' => $this->task->id,
            'pinned' => $newPinnedState,
        ];
        
        $this->emit('taskUpdated');
    }
    
  3. 修改前端第二个按钮,绑定Livewire的$pinned状态
    把Blade静态变量替换为Livewire属性,推荐用Alpine绑定确保实时更新:

    @if ($isMyTask)
        <a href="#" 
            x-data="{ pinned: @entangle('pinned') }"
            x-tooltip.placement.top.raw="`${pinned ? 'Unpin' : 'Pin'}`"
            wire:click="togglePinned" 
            wire:key="pinned-{{ $task->id }}">
            <i :class="pinned ? 'fas fa-fw fa-thumbtack' : 'fal fa-fw fa-thumbtack'" aria-hidden="true"></i>
        </a>
        {{ 'KEY ID' . $task->id . ' ' . ($pinned ? 'pinned' : 'unpinned') }}
    @endif
    

    若不想用Alpine,也可直接依赖Livewire动态渲染,需给wire:key加上$pinned确保元素重新渲染:

    @if ($isMyTask)
        <a href="#" 
            x-tooltip.placement.top.raw="{{ $pinned ? 'Unpin' : 'Pin' }}"
            wire:click="togglePinned" 
            wire:key="pinned-{{ $task->id }}-{{ $pinned }}">
            <i class="{{ $pinned ? 'fas' : 'fal' }} fa-fw fa-thumbtack" aria-hidden="true"></i>
        </a>
        {{ 'KEY ID' . $task->id . ' ' . ($pinned ? 'pinned' : 'unpinned') }}
    @endif
    
  4. 移除Blade中的静态$pinned计算
    删除@php块里的$pinned = $task_user?->pivot->pinned === 1;,改用Livewire组件的属性。

这样修改后,点击按钮时Livewire会同步更新$pinned状态,前端能立即切换图标和tooltip内容。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.13 19:16:01