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>

现在当父组件添加或删除待办事项时,子组件将自动更新以反映新的计数。

为什么 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],在父组件中添加待办事项不会更新子组件的计数。

工作原理

当你添加 #[Reactive] 时:

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

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

性能注意事项

谨慎使用响应式属性

响应式属性需要在每次父组件更新时在服务器和客户端之间发送额外的数据。只在用例需要时使用 #[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;
}

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

了解更多

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