Skip to content
全部文档

Reactive

#[Reactive] 属性使子组件的属性在父组件更改传入的值时自动更新。

基本用法

#[Reactive] 属性应用到任何应响应父级变更的属性上:

php
<?php // resources/views/components/⚡todo-count.blade.php

use Livewire\Attributes\Reactive;
use Livewire\Attributes\Computed;
use Livewire\Component;

new class extends Component {
    #[Reactive] // [tl! highlight]
    public $todos;

    #[Computed]
    public function count()
    {
        return $this->todos->count();
    }
};
?>

<div>
    Count: {{ $this->count }}
</div>

现在当父组件添加或移除 todo 时,子组件会自动更新以反映新的计数。

为什么 props 默认不是响应式的

默认情况下,Livewire 的 props 不是响应式的。当父组件更新时,只有父组件的状态会发送到服务器——不包括子组件的。这能最小化数据传输并提升性能。

没有 #[Reactive] 时会发生以下情况:

php
<?php // resources/views/components/⚡todos.blade.php

use Livewire\Component;

new class extends Component {
    public $todos = [];

    public function addTodo($text)
    {
        $this->todos[] = ['text' => $text];
        // Child components with $todos props won't automatically update
    }
};
?>

<div>
    <livewire:todo-count :$todos />

    <button wire:click="addTodo('New task')">Add Todo</button>
</div>

若子组件的 $todos 属性没有 #[Reactive],在父组件中添加 todo 不会更新子组件的计数。

工作原理

添加 #[Reactive] 后:

  1. 父组件更新其 `$todos` 属性
  2. 父组件在响应期间将新的 `$todos` 值发送给子组件
  3. 子组件使用新值自动重新渲染

这创建了类似于 Vue 或 React 等前端框架的「响应式」关系。

性能考量

WARNING

谨慎使用响应式属性

响应式属性要求在每次父组件更新时在服务器与客户端之间发送额外数据。仅在你的用例确实需要时才使用 #[Reactive]

何时使用:

  • 子组件显示在父组件中会变化的数据
  • 子组件需要与父组件状态保持同步
  • 你正在构建紧密耦合的父子关系

何时不要使用:

  • 初始数据只传递一次且永不变化
  • 子组件管理自己的独立状态
  • 性能至关重要且不需要更新

示例:实时搜索结果

下面是一个带有响应式结果的搜索组件实用示例:

php
<?php // resources/views/components/⚡search.blade.php

use Livewire\Component;
use App\Models\Post;

new class extends Component {
    public $query = '';

    public function posts()
    {
        return Post::where('title', 'like', "%{$this->query}%")->get();
    }
};
?>

<div>
    <input type="text" wire:model.live="query" placeholder="Search posts...">

    <livewire:search-results :posts="$this->posts()" /> <!-- [tl! highlight] -->
</div>
php
<?php // resources/views/components/⚡search-results.blade.php

use Livewire\Attributes\Reactive;
use Livewire\Component;

new class extends Component {
    #[Reactive] // [tl! highlight]
    public $posts;
};
?>

<div>
    @foreach($posts as $post)
        <div wire:key="{{ $post->id }}">{{ $post->title }}</div>
    @endforeach
</div>

用户输入时,父组件的 $posts 会变化,子组件的结果会自动更新。

替代方案:事件

对于松耦合组件,可考虑使用事件而非响应式 props:

php
// Parent dispatches event
$this->dispatch('todos-updated', todos: $this->todos);

// Child listens for event
#[On('todos-updated')]
public function handleTodosUpdate($todos)
{
    $this->todos = $todos;
}

事件提供更大的灵活性,但需要组件之间进行显式通信。

了解更多

有关父子通信和组件架构的更多信息,请参阅 嵌套组件文档