Skip to content
全部文档

Modelable

#[Modelable] 属性指定子组件中可被父组件通过 wire:model 绑定的属性。

基本用法

#[Modelable] 属性应用到子组件的属性上,使其可绑定:

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

use Livewire\Attributes\Modelable;
use Livewire\Component;

new class extends Component {
    #[Modelable] // [tl! highlight]
    public $value = '';
};
?>

<div>
    <input type="text" wire:model="value">
</div>

现在父组件可以像绑定任何其他输入元素一样绑定到该子组件:

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

use Livewire\Component;

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

    public function addTodo()
    {
        // Use $this->todo here...
    }
};
?>

<div>
    <livewire:todo-input wire:model="todo" /> <!-- [tl! highlight] -->

    <button wire:click="addTodo">Add Todo</button>
</div>

用户在 todo-input 组件中输入时,父组件的 $todo 属性会自动更新。

工作原理

没有 #[Modelable] 时,你需要手动处理父子之间的双向通信:

php
// Without #[Modelable] - manual approach
<livewire:todo-input
    :value="$todo"
    @input="todo = $event.value"
/>

#[Modelable] 属性通过允许直接在组件上使用 wire:model 简化了这一点。

构建可复用输入组件

#[Modelable] 非常适合创建用起来像原生 HTML 输入的自定义输入组件:

php
<?php // resources/views/components/⚡date-picker.blade.php

use Livewire\Attributes\Modelable;
use Livewire\Component;

new class extends Component {
    #[Modelable]
    public $date = '';
};
?>

<div>
    <input
        type="date"
        wire:model="date"
        class="border rounded px-3 py-2"
    >
</div>
blade
{{-- Usage in parent --}}
<livewire:date-picker wire:model="startDate" />
<livewire:date-picker wire:model="endDate" />

WARNING

组件的根元素不能是带有 wire:model 的表单控件。请用 <div> 等包装元素包裹输入。Livewire 会在根元素上注入 wire:modelx-modelable 以连接父级绑定——同一元素上的第二个 wire:model 会造成冲突。

修饰符

父组件可以使用 wire:model 修饰符来控制时机和网络请求:

blade
{{-- Live updates on every keystroke --}}
<livewire:todo-input wire:model.live="todo" />

{{-- Debounce updates --}}
<livewire:todo-input wire:model.live.debounce.500ms="todo" />

{{-- Throttle updates --}}
<livewire:todo-input wire:model.live.throttle.500ms="todo" />

INFO

组件上的基于事件的修饰符

.blur.change.enter 等基于事件的修饰符控制的是特定元素上的 DOM 事件,而非响应式组件绑定。要控制 modelable 组件的同步时机,请将这些修饰符放在子组件内的实际输入元素上:

blade
&#123;&#123;-- Parent --&#125;&#125;
<livewire:todo-input wire:model="todo" />

&#123;&#123;-- Child component --&#125;&#125;
<input wire:model.blur="value" />

示例:自定义富文本编辑器

下面是一个更复杂的富文本编辑器组件示例:

php
<?php // resources/views/components/⚡rich-editor.blade.php

use Livewire\Attributes\Modelable;
use Livewire\Component;

new class extends Component {
    #[Modelable]
    public $content = '';
};
?>

<div>
    <div
        x-init="
            // Initialize your rich text editor library here
            editor.on('change', () => {
                $wire.content = editor.getContent()
            })
        "
    >
        <!-- Rich text editor UI -->
    </div>
</div>
blade
{{-- Usage --}}
<livewire:rich-editor wire:model="postContent" />

限制

WARNING

每个组件只能有一个 modelable 属性

目前 Livewire 每个组件仅支持一个 #[Modelable] 属性,因此只有第一个会被绑定。

何时使用

在以下情况使用 #[Modelable]

  • 创建可复用输入组件(日期选择器、颜色选择器、富文本编辑器)
  • 构建需要与 `wire:model` 配合使用的表单组件
  • 将第三方 JavaScript 库包装为 Livewire 组件
  • 创建带有特殊验证或格式化的自定义输入

了解更多

有关父子通信和数据绑定的更多信息,请参阅 嵌套组件文档