Laravel-Livewire是如何激发和收听事件的? [英] How does Laravel-Livewire fires events and listens to them?

查看:30
本文介绍了Laravel-Livewire是如何激发和收听事件的?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我有两个加载Livewire组件的视图

<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' );
}

由于某些原因,这始终以"I should not get here if there is a dd before"结束,那么我应该更改什么?为什么我的听众没有在听,或者没有被解雇?我尝试过不同的方法,但都没有成功。

推荐答案

简短答案

简而言之,事件是在组件(PHP)中发出的-发出哪些事件以及相应的哪些数据通过响应发送。livewire处理响应,并检查是否发出了任何事件-如果是,它告诉与该事件相对应的JavaScript对象已经发出了这样的事件-这些JavaScript对象将发出它们自己的网络请求来处理该事件。

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


答案越长

当Livewire处理请求时,它将确定要调用哪些方法和设置哪些属性。它将看到您正在调用一个方法,调用该方法将通过$this->emit()发出事件,在您的示例中是方法setAnswer。这样做之后,Livewire将在响应中添加您发出了一个事件。这些事件的侦听器使用JavaScript,因为它不直接与其他PHP组件通信。

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

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

调度的浏览器事件也是如此,它们也会出现在这里,

对于我在此处显示的内容,这是从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下的数据,它将发出这些事件(类似于在原生JavaScript中使用Livewire.emit('event-name', ...data)),对应于不同组件的JavaScript对象将获取这些事件并向相应组件发出新的请求。让我们扩展我们的示例,

protected $listeners = ['myListener'];

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

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

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

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

这篇关于Laravel-Livewire是如何激发和收听事件的?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆