事件機制是一種非常典型的通訊方式,可以在程式中的不同對象之間傳遞資訊,也可以在一個應用的不同層面進行溝通協作。微信小程式中也采用了事件機制,我們這次來了解一下微信小程式架構提供的事件處理機制。
小程式官方文檔對事件的定義是:- 事件是視圖層到邏輯層的通信方式
- 事件可以将使用者的行為回報到邏輯層進行處理
- 事件可以綁定在元件上,當達到觸發事件,就會執行邏輯層中對應的事件處理函數。
- 事件對象可以攜帶額外資訊,如 id, dataset, touches。
從這裡我們可以看到,官方文檔主要将事件用于小程式中針對使用者互動行為的處理,即視圖層(WXML)到邏輯層(Page)的通信,邏輯層收到這些使用者行為事件後,可以進行業務處理,然後根據情況回報或不回報結果給使用者。
我們今天就撇開事件的其他用法,專門就來了解小程式視圖層和邏輯層之間的事件用法。
總體上來說,小程式中的事件機制在工作原理上來講,和HTML DOM的事件機制是一緻的。在HTML中,我們可以通過在HTML元素上設定一個如onclick="clickHandler(event)"的屬性來綁定使用者的頁面點選事件處理函數。而在WXML中,我們為一個元件綁定一個事件處理函數,可以使用如下文法來完成:
這裡的bindtap就可以了解為将tap(點選)事件,綁定到一個名為tapName的事件處理函數上來進行處理。然後在相應的Page代碼中,我們需要定義這個tapName函數:
這樣完成了一個簡單的tap事件的處理。當我們在小程式的界面上去點選這個顯示為Click me的view元件的時候,view元件捕獲到這個tap動作,然後告訴Page中的tapName函數,要對這個動作進行處理,同時,它也為tapName函數提供了足夠多的資訊,也就是event對象,來幫助我們更好更精準的處理我們的業務邏輯。我們可以來看一下我們這個例子中的event對象裡面包含了哪些内容:
event
這裡我們可以看到,在event對象中,包含了事件的名稱,事件目标對象的資訊,以及事件發生的在界面上的位置資訊等等。我們在元件上設定的data-hi屬性的值,也在target中的dataset上被攜帶了過來,這是比較有用的,在實際開發中,我們可以利用這個特性,來傳遞更多視圖層的資訊到邏輯層進行處理。
如果你有DOM程式設計的經驗,你就會在這裡想到,小程式裡事件的冒泡和非冒泡是怎麼處理的?如果你還不了解什麼是事件冒泡,那我在這裡解釋一下:
在HTML或者WXML這些基于XML的樹形結構的界面布局方式中,元素與元素之間是有層級關系的,子級元素上觸發的事件,可以向父級元素逐層向上傳遞,是以,父級元素上也可以捕獲子級元素上的事件并進行邏輯處理。
這種事件冒泡的機制,在實際的開發中也經常會用到,是以我們有必要來了解下在小程式中,是如何來使用冒泡事件的。WXML中分别提供了兩種方式,用來綁定事件處理函數:
1. 使用 bind 開頭的事件綁定,這種綁定不會阻止冒泡事件向上冒泡
2. 使用 catch 開頭的事件綁定,這種綁定可以阻止冒泡事件向上冒泡
直覺起見,我們直接來看一個示例代碼:
index.wxml
index.wxss
在這個示例代碼中,有三個逐級嵌套的view元素,最裡層的是content元素,最外層的為outer-container元素。最裡層和最外層的元素上,使用了bind屬性綁定了tap事件的處理函數,而中間的innner-container上,使用了catch屬性進行tap事件綁定。
然後,我們嘗試在content上點選一下,可以看到這樣的結果:
點選content的結果
content和inner-container元素的tap事件處理函數被執行了,而outer-container元素的沒有被執行。這說明在點選content的過程中,産生的tap事件向父級元素傳遞,而作為content元素的父級元素inner-container, 它使用了能阻止事件冒泡的catch方式,是以它在捕獲通過冒泡形式過來的子級元素事件并執行事件處理函數後,讓該事件停止向上傳遞,是以同樣是父級元素的outer-contaner,就不再能收到這個冒泡事件了。
然後,來看一下,在不同層級的元素捕獲的event對象,在資料方面有什麼特點:
我們可以看到,在content的tap事件處理函數中,event裡面的target和currentTarget的id都是content。
而在inner-container中的event對象裡,target的id為content,而currentTarget的id是inner-content。
由此我們可以知道,event對象中的target是事件産生的源頭元件,而currentTarget則是目前捕獲這個事件的元件。
event對象中還包含其他一些有用的資訊,如touches和changedTouches表示一個或多個手指在螢幕上的觸摸位置和變動位置等資訊,可以用來實作多點觸摸的進階手勢處理。
最後,關于事件冒泡,有一點是值得注意一下的:在微信小程式中,并不是所有事件都是冒泡的,從官方文檔了解到,<canvas>元件的觸摸事件不可冒泡。