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>
    计数:{{ $this->count }}
</div>

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

为什么属性默认不是响应式的

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

以下是没有 #[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];
        // 具有 $todos 属性的子组件不会自动更新
    }
};
?>

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

    <button wire:click="addTodo('新任务')">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="搜索帖子...">

    <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>{{ $post->title }}</div>
    @endforeach
</div>

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

替代方法:事件

对于松耦合的组件,考虑使用事件而不是响应式属性:

php
// 父组件分发事件
$this->dispatch('todos-updated', todos: $this->todos);

// 子组件监听事件
#[On('todos-updated')]
public function handleTodosUpdate($todos)
{
    $this->todos = $todos;
}

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

了解更多

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