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