此组件(display-section)在循环中调用子组件... -6ren">
gpt4 book ai didi

laravel - Laravel-Livewire 如何触发事件并监听它们?

转载 作者:行者123 更新时间:2023-12-02 01:55:51 35 4
gpt4 key购买 nike

我有两个加载 livewire 组件的 View

<x-layouts.formularies>
<livewire:formularies.edit.display-section :section="$section->id" :formulary="$formulary->id" />
</x-layouts.formularies>

此组件(display-section)在循环中调用子组件...

<div class="letter mx-auto" id="section-holder">
<div class="paper-title d-flex justify-content-between">
@foreach($questionnaire->getData( 'logos', [] ) as $logo)
<img src="{{ asset($logo[ 'path' ]) }}" class="img-fluid h-100" />
@endforeach
</div>

<div class="section-questions">
@foreach($section->questions as $question)
<livewire:formularies.edit.display-row :question="$question->id"
:formulary="$formulary->id" :wire:key="$question->id" />
<hr />
@endforeach
</div>
</div>

现在,这是display-row组件:

<div class="card-body text-center p-1">
<div class="btn-group m-1" role="group" aria-label="question-{{ $question->id }}">
@foreach($question->answers as $answer)
<input type="radio"
wire:model="answer"
:wire:key="$question->id . '-' . $answer->id"
wire:click="setAnswer"
class="btn-check"
value="{{ $answer->id }}"
name="question-{{ $question->id }}"
id="question-{{ $question->id }}-{{ $answer->id }}"
autocomplete="off" />
<label class="btn btn-outline-teal text-dark mb-0"
for="question-{{ $question->id }}-{{ $answer->id }}">{{ $answer->statement }}</label>
@endforeach
</div>
</div>

当用户从单选按钮中选择一个选项时,它会执行一些数据库操作并触发父组件应监听的事件(display-section) :

public function setAnswer()
{
$this->emit( 'formularyUpdated', $this->formulary->id );
FormularyUpdated::dispatch( $this->formulary, $this->question, $this->answer );
dd( 'I should not get here if there is a dd before' );
}

如您所见,此函数会发出一个带有公式 ID 的 formularyUpdated 事件。在 DisplaySection 中我有这个:

protected $listeners = [
'sectionAdvanced',
'formularyUpdated',
];

/**
*
*/
public function formularyUpdated( Formulary $formulary )
{
dd( 'This dd should stop the execution' );
}

出于某种原因,这总是以“如果之前有 dd,我不应该到达这里” 那么,我应该更改什么?为什么我的听众不听或者没有被解雇?我尝试了不同的方法但没有运气。

最佳答案

简短回答

简单总结一下;事件在组件 (PHP) 中发出 - 发出哪些事件以及随之而来的哪些数据通过响应发送。 Livewire 处理响应,并检查是否发出任何事件 - 如果是,它会告诉与该事件对应的 JavaScript 对象,发出了此类事件 - 并且这些 JavaScript 对象将发出自己的网络请求来处理该事件。 p>

换句话说,事件的整个监听和发出实际上发生在 JavaScript 中,即 Livewire 在服务器之间来回发出的响应和请求中。


较长的答案

当 Livewire 处理请求时,它会确定要调用哪些方法以及要设置哪些属性。它将看到您正在调用一个方法,并且调用该方法会通过 $this->emit() 发出事件,在您的例子中是方法 setAnswer。执行此操作后,Livewire 将在响应中添加您发出的事件。这些事件的监听器位于 JavaScript 中 - 因为它不直接与其他 PHP 组件通信。

因此,您的请求被触发,您发出事件,并且响应返回一些指示事件已发出的内容。如果我们查看该请求的网络响应,它可能看起来像这样(这是来 self 的本地环境的伪代码/测试数据),

enter image description here

如您所见,它有一个发出的事件。我们可以发出更多事件,它们将按照发出的顺序出现。

enter image description here

同样的情况也适用于分派(dispatch)的浏览器事件,它们也会出现在这里,

enter image description here

对于我在这里展示的内容,这是从 wire:click 调用的方法,

public function myMethod()
{
$this->emit('my-first-emit', 'My first emit data');
$this->emit('my-second-emit', ['This time', 'the emit', 'passes an', 'array']);
$this->dispatchBrowserEvent('browser-dispatched-event', 'My browser-event data!');
}

因此,当 Livewire 收到响应时,它会检查它是否具有需要处理的某些效果 - 是否有任何调度的浏览器事件、发出的 Livewire 事件或其他任何内容。

如果响应在 effects.emits 下携带数据,它将发出这些事件,类似于使用 Livewire.emit('event-name', ...data) 在 native JavaScript 中,与不同组件对应的 JavaScript 对象将拾取这些对象并向相应组件发出新请求。让我们扩展我们的示例,

protected $listeners = ['myListener'];

public function myMethod()
{
$this->emit('myListener', 'My first emit data');
}

public function myListener($data = null)
{
// Do something with $data
}

现在,当我们调用方法 myMethod 时,就会触发网络请求,正如我们之前所看到的那样。但现在我们还收到了第二个请求,这是我们之前监听的已发出事件。我们再次可以使用网络检查器,这次我们对请求感兴趣,而不是响应。

正如我们所看到的,有两个请求 - 第一个是发出事件的请求,第二个是监听该事件的请求。第二个请求有一个update参数,其类型为fireEvent,它还有一些其他的Livewire数据,参数就是数据。这就是魔法发生的地方,以及它如何监听这些事件。

enter image description here

关于laravel - Laravel-Livewire 如何触发事件并监听它们?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/69616842/

35 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com