wire:ref
Livewire 中的 Refs 提供了一种命名方式,进而可定位 Livewire 内的单个元素或组件。
它们适用于向特定元素派发事件或流式传输内容。
它们是用 class/id 定位元素的更整洁替代方案,但概念上类似。
常见用例包括:
- 向特定组件派发事件
- 使用 `$refs` 定位元素
- 向特定元素流式传输内容
下面逐一说明。
派发事件
在 Livewire 事件系统中,Refs 是定位特定子组件的好方法。
考虑下面这个监听 close 事件的 Livewire 模态框组件:
php
<?php
new class extends Livewire\Component {
public bool $isOpen = false;
// ...
#[On('close')]
public function close()
{
$this->isOpen = false;
}
};
?>
<div wire:show="isOpen">
{{ $slot }}
</div>在组件标签上添加 wire:ref 后,即可用 ref: 参数直接向它派发 close 事件:
php
<?php
new class extends Livewire\Component {
public function save()
{
//
$this->dispatch('close')->to(ref: 'modal');
}
};
?>
<div>
<!-- ... -->
<livewire:modal wire:ref="modal">
<!-- ... -->
<button wire:click="save">Save</button>
</livewire:modal>
</div>访问 DOM 元素
给 HTML 元素加上 wire:ref 后,可通过 $refs 魔术属性访问它。
考虑一个实时更新的字符计数器:
php
<div>
<textarea wire:model="message" wire:ref="message"></textarea>
Characters: <span wire:ref="count">0</span>
<!-- ... -->
</div>
<script>
this.$refs.message.addEventListener('input', (e) => {
this.$refs.count.textContent = e.target.value.length
})
</script>访问 $wire
若要访问带有 ref 的组件的 $wire,可通过该元素上的 .$wire 属性:
php
<div>
<!-- ... -->
<livewire:modal wire:ref="modal">
<!-- ... -->
<button wire:click="save()">Save</button>
</livewire:modal>
</div>
<script>
this.$intercept('save', ({ onFinish }) => {
onFinish(() => {
this.$refs.modal.$wire.close()
})
})
</script>流式传输内容
Livewire 支持用 CSS 选择器将内容直接流式传输到组件内的元素,但 wire:ref 是更方便、更易发现的方式。
考虑下面这个组件:它在 LLM 生成答案时直接将内容流式传输出来:
php
<?php
new class extends Livewire\Component {
public $question = '';
public function ask()
{
Ai::ask($this->question, function ($chunk) {
$this->stream($chunk)->to(ref: 'answer');
});
$this->reset('question');
}
};
?>
<div>
<input type="text" wire:model="question">
<button wire:click="ask"></button>
<h2>Answer:</h2>
<p wire:ref="answer"></p>
</div>动态 refs
Refs 在循环及其他动态上下文中也能完美工作。
下面是多个模态框实例的示例:
php
@foreach($users as $index => $user)
<livewire:modal
wire:key="{{ $user->id }}"
wire:ref="{{ 'user-modal-' . $user->id }}"
>
<!-- ... -->
</livewire>
@endforeach作用域行为
Refs 的作用域限于当前组件。这意味着你可以定位组件内的任意元素,但不能定位页面上其他组件中的元素。
若组件内多个元素具有相同的 ref 名称,将使用遇到的第一个。
参考
blade
wire:ref="name"此指令没有修饰符。