昨天提到了互動事件(Action)基本上能解決大部分頁面中互動的需求,但若要能夠跨元件來進行互動,例如呼叫其他元件中的 Function 就要靠今天的 $emit
事件啦~
不光是能夠從 Template Blade 中使用,也能夠從 Livewire 元件中的 Function 使用,甚至還能在 JavaScript 中呼叫使用。
<button wire:click="$emit('postAdded')">
$this->emit('postAdded');
<script>
Livewire.emit('postAdded')
</script>
不過在使用 emit
前必須先在各個有要用到的元件中先宣告監聽才能夠成功透過 $emit
呼叫該元件中的 Function。
注意: 這邊是很多人常常忘記做的步驟而導致怎樣都呼叫不到,且
emit
是全域呼叫並不會提示是否呼叫成功或是報錯。
class Day8 extends Component
{
...
protected $listeners = ['toggleTitle' => 'toggleTitle'];
public function render()
{
return view('livewire.example.day8');
}
public function toggleTitle()
{
...
}
}
外面 $emit
的名稱也可以跟實際函數名稱的不一樣,像是這邊我這個元件中使用的是 setTitleVisible ()
而外面一樣透過 $emit('toggleTitle')
來呼叫。
protected $listeners = ['toggleTitle' => 'setTitleVisible'];
要傳遞參數也是非常簡單的事:
$this->emit('postAdded', $post->id);
protected $listeners = ['postAdded'];
public function postAdded($id)
{
...
}
由於 $emit
的範圍可涵蓋至目前頁面上所有的 Livewire,也能做全域呼叫使用,換句話說就是能觸發不同 Livewire 元件中同名的 Function,可以參考 Github 上 Day8 的範例。但有時候並不需要呼叫到全部的元件,那這時候就有以下幾種方法可以只呼叫特定元件中的 Function:
emitUp
$this->emitUp('postAdded');
<button wire:click="$emitUp('postAdded')">
emitTo
$this->emitTo('counter', 'postAdded');
<button wire:click="$emitTo('counter', 'postAdded')">
emitSelf
$this->emitSelf('postAdded');
<button wire:click="$emitSelf('postAdded')">
資料儲存成功後,要在頁面顯示成功的訊息還是需要透過 JS 來執行,畢竟那些放在按鈕中的 wire:click()
事件沒辦法回傳值,也沒辦法在 PHP 呼叫 JS 的 Function。那就只能夠過這個方法來做產生操作回饋。
因此我們可以在 blade
的 script
區塊中建立一個監聽器,並透過 alert
來顯示操作成功的訊息:
<script>
Livewire.on('postAdded', () => {
alert('文章已經發布囉!');
})
</script>
之後的 $emit('postAdded')
也會觸發上面的 JS 區塊囉 ~
注意:這裡的
<script>
必須放在 Layout 的頁面才會生效,或者使用@stack('scripts')
及@push('scripts')
來將 JS 的部分塞回 Layout 中才會生效,程式碼可以參考我的 Day8 示範。*如果覺得複雜建議使用下方瀏覽器監聽的方法,會簡單很多!!
也可以直接觸發瀏覽器的監聽事件,但這邊就要使用 dispatchBrowserEvent ()
而不是 emit()
:
$this->dispatchBrowserEvent('postAdded');
在 blade
上則要用 window.addEventListener
來建立監聽:
<script>
window.addEventListener('postAdded', () => {
alert('文章已經發布囉!');
})
</script>
運行之後打開 http://127.0.0.1:8000/day8
就能看到今天的範例啦!
檔案的話分別在:
app\Http\Livewire\Example\Day8.php
resources\views\livewire\example\day8.balde.php
今天的範例會演示:
$emit
同時呼叫 Day8
與 Day8Child
中的 toggleTitle()
。$emit
的事件。dispatchBrowserEvent
事件。