iT邦幫忙

2021 iThome 鐵人賽

DAY 30
0
Modern Web

Laravel Livewire:不用 Vue 跟 jQuery 居然也能讓 Laravel 的畫面動起來 ?!系列 第 30

Day 29 | 很像 Vue 的 AlpineJS(四): x-on

x-on

x-on 可以簡單的用從 DOM 中來觸發事件,像是最常用的按鈕:

<button x-on:click="alert('Hello World!')">Say Hi</button>

縮寫

跟 Vue 一樣都能夠把 x-on:click 縮寫成 @click,像是上面的範例就可以寫成這樣:

<button @click="alert('Hello World!')">Say Hi</button>

事件物件

如果有需要用到 JavaScritp 的原生事件,可以透過 AlpineJS 的魔術方法 $event 來取得:

範例會取得寫在 <button> 中的 message 屬性的值,因此會印出 「Hello World」

<button @click="alert($event.target.getAttribute('message'))" message="Hello World">Say Hi</button>

也可以寫成這樣

<button @click="handleClick">...</button>
 
<script>
    function handleClick(e) {
        // Now you can access the event object (e) directly
    }
</script>

或是

<button @click="e => console.log(e)">...</button>

鍵盤輸入事件

AlpineJS 也能在鍵盤 keydownkeyup時觸發事件:

範例為按下 enter 後觸發事件

<input type="text" @keyup.enter="alert('Submitted!')">

同時按下多個按鍵

如果有需要同時按兩個鍵才觸發,就可以這樣寫:

必須同時按下 shift + enter 才會觸發

<input type="text" @keyup.shift.enter="alert('Submitted!')">

或是更多 shift + enter + a

<input type="text" @keyup.shift.a.enter="alert('Submitted!')">

基本上所有按鍵都能拿來當觸發條件,但同時綁多個可能多嘗試一下順序排列。如果要找更多按鍵的名稱可以參考 MDN KeyboardEvent.key

自定義事件

AlpineJS 的監聽器是包裝後的原生監聽器,因此可以接收來自任何 DOM 的事件或是自定義的事件:

<div x-data @foo="alert('Button Was Clicked!')">
    <button @click="$event.target.dispatchEvent(new CustomEvent('foo', { bubbles: true }))">...</button>
</div>

或是更簡單的寫法,透過魔術方法 $dispatch

<div x-data @foo="alert('Button Was Clicked!')">
  <button @click="$dispatch('foo')">...</button>
</div>

修飾符

.prevent

<form @submit.prevent="console.log('submitted')" action="/foo">
    <button>Submit</button>
</form>

正常情況下當 submit 的時候會觸發 action 將表單的內容提交到 /foo。如果使用了 @submit.prevent 就只會執行 @submit 裡面寫的指令,而不是像原本一樣轉跳至 /foo


.stop

會阻止外層的事件執行,像是:

由於裡面使用了 @click.stop 因此外層的 @click 就不會執行了。

<div @click="console.log('I will not get logged')">
    <button @click.stop>Click Me</button>
</div>

.outside

可以監聽該元素以外的點擊事件。

注意:

  1. 會監聽該元素以外的事件,意味著點擊該元素則不會觸發 @click
  2. 對整個畫面都有效,即便點擊的地方在 x-data 所包含的區塊外
<div class="shadow-lg w-96 p-5" >
    <div  @click.outside="console.log('click!!')">按鈕</div>
</div>

.window

使用後該 @click 將會監聽整個 window物件 而不是原本的標籤。

像是在畫面上按下 ESC 則會觸發該事件

<div @keyup.escape.window="...">...</div>

.document

如同上面的 .window,只是變成監聽整個 document


.debounce

與昨天的很像,會在觸發後某段時間內沒有再次被觸發才會生效,預設為250ms。可以有效防止短時間過快的觸發,尤其是在 @input 上。且一樣可以自行設置 debounce 的時間。

簡單來說,預設情況下,在不斷輸入文字的同時至少要停止輸入超過250ms,才會觸發 @input 事件。

<input @input.debounce.1000ms="doSomething">

.throttle

簡單來說,就是會在觸發後冷卻某段時間才會在觸發,預設 250ms。

官方文件舉一個很好的例子:在監聽捲軸滑動時,通常滑一下都會觸發超級多個事件,而我們根本不需要那麼頻繁的觸發。透過 .throttle 就可以在某特定時間內才觸發一次就好,像是預設的話每隔 250ms 才會執行一次自訂的滑動捲軸事件。

<div @scroll.window.throttle="handleScroll">...</div>

.self

可以確定是點在自己這個元素本身,而不是被本身包含的字元素。

範例中必須點擊 div 的區塊才會有作用,如果點到裡面的 button 的話也不會觸發寫在 div 上的 @click

<div @click.self="alert('click')">
    <button>按鈕</button>
</div>

上一篇
Day 28 | 很像 Vue 的 AlpineJS(三): x-model
下一篇
Day 30 | 很像 Vue 的 AlpineJS(五): 與 Livewire 共享資料
系列文
Laravel Livewire:不用 Vue 跟 jQuery 居然也能讓 Laravel 的畫面動起來 ?!34

尚未有邦友留言

立即登入留言