新聞中心
事件
什么是事件
- 事件是視圖層到邏輯層的通訊方式。
- 事件可以將用戶的行為反饋到邏輯層進(jìn)行處理。
- 事件可以綁定在組件上,當(dāng)達(dá)到觸發(fā)事件,就會執(zhí)行邏輯層中對應(yīng)的事件處理函數(shù)。
- 事件對象可以攜帶額外信息,如 id, dataset, touches。
事件的使用方式
- 在組件中綁定一個事件處理函數(shù)。
如bindtap,當(dāng)用戶點擊該組件的時候會在該頁面對應(yīng)的Page中找到相應(yīng)的事件處理函數(shù)。

我們提供的服務(wù)有:成都做網(wǎng)站、網(wǎng)站制作、微信公眾號開發(fā)、網(wǎng)站優(yōu)化、網(wǎng)站認(rèn)證、田東ssl等。為成百上千家企事業(yè)單位解決了網(wǎng)站和推廣的問題。提供周到的售前咨詢和貼心的售后服務(wù),是有科學(xué)管理、有技術(shù)的田東網(wǎng)站制作公司
- 在相應(yīng)的Page定義中寫上相應(yīng)的事件處理函數(shù),參數(shù)是event。
Page({
tapName: function(event) {
console.log(event)
}
})
- 可以看到log出來的信息大致如下:
{
"type":"tap",
"timeStamp":895,
"target": {
"id": "tapTest",
"dataset": {
"hi":"WeChat"
}
},
"currentTarget": {
"id": "tapTest",
"dataset": {
"hi":"WeChat"
}
},
"detail": {
"x":53,
"y":14
},
"touches":[{
"identifier":0,
"pageX":53,
"pageY":14,
"clientX":53,
"clientY":14
}],
"changedTouches":[{
"identifier":0,
"pageX":53,
"pageY":14,
"clientX":53,
"clientY":14
}]
}
使用WXS函數(shù)響應(yīng)事件
基礎(chǔ)庫 2.4.4 開始支持,低版本需做 兼容處理。
從基礎(chǔ)庫版本2.4.4開始,支持使用WXS函數(shù)綁定事件,WXS函數(shù)接受2個參數(shù),第一個是event,在原有的event的基礎(chǔ)上加了event.instance對象,第二個參數(shù)是ownerInstance,和event.instance一樣是一個ComponentDescriptor對象。具體使用如下:
- 在組件中綁定和注冊事件處理的WXS函數(shù)。
Click me!
**注:綁定的WXS函數(shù)必須用{{}}括起來**
- test.wxs文件實現(xiàn)tapName函數(shù)
function tapName(event, ownerInstance) {
console.log('tap wechat', JSON.stringify(event))
}
module.exports = {
tapName: tapName
}
ownerInstance包含了一些方法,可以設(shè)置組件的樣式和class,具體包含的方法以及為什么要用WXS函數(shù)響應(yīng)事件。
事件詳解
事件分類
事件分為冒泡事件和非冒泡事件:
- 冒泡事件:當(dāng)一個組件上的事件被觸發(fā)后,該事件會向父節(jié)點傳遞。
- 非冒泡事件:當(dāng)一個組件上的事件被觸發(fā)后,該事件不會向父節(jié)點傳遞。
WXML的冒泡事件列表:
| 類型 | 觸發(fā)條件 | 最低版本 |
|---|---|---|
| touchstart | 手指觸摸動作開始 | |
| touchmove | 手指觸摸后移動 | |
| touchcancel | 手指觸摸動作被打斷,如來電提醒,彈窗 | |
| touchend | 手指觸摸動作結(jié)束 | |
| tap | 手指觸摸后馬上離開 | |
| longpress | 手指觸摸后,超過350ms再離開,如果指定了事件回調(diào)函數(shù)并觸發(fā)了這個事件,tap事件將不被觸發(fā) | 1.5.0 |
| longtap | 手指觸摸后,超過350ms再離開(推薦使用longpress事件代替) | |
| transitionend | 會在 WXSS transition 或 wx.createAnimation 動畫結(jié)束后觸發(fā) | |
| animationstart | 會在一個 WXSS animation 動畫開始時觸發(fā) | |
| animationiteration | 會在一個 WXSS animation 一次迭代結(jié)束時觸發(fā) | |
| animationend | 會在一個 WXSS animation 動畫完成時觸發(fā) | |
| touchforcechange | 在支持 3D Touch 的 iPhone 設(shè)備,重按時會觸發(fā) | 1.9.90 |
注:除上表之外的其他組件自定義事件如無特殊聲明都是非冒泡事件,如 form 的submit事件,input 的input事件,scroll-view 的scroll事件,(詳見各個組件)
普通事件綁定
事件綁定的寫法類似于組件的屬性,如:
Click here!
如果用戶點擊這個 view ,則頁面的 handleTap 會被調(diào)用。
事件綁定函數(shù)可以是一個數(shù)據(jù)綁定,如:
Click here!
此時,頁面的 this.data.handlerName 必須是一個字符串,指定事件處理函數(shù)名;如果它是個空字符串,則這個綁定會失效(可以利用這個特性來暫時禁用一些事件)。
自基礎(chǔ)庫版本 1.5.0 起,在大多數(shù)組件和自定義組件中, bind 后可以緊跟一個冒號,其含義不變,如 bind:tap ?;A(chǔ)庫版本 2.8.1 起,在所有組件中開始提供這個支持。
綁定并阻止事件冒泡
除 bind 外,也可以用 catch 來綁定事件。與 bind 不同, catch 會阻止事件向上冒泡。
例如在下邊這個例子中,點擊 inner view 會先后調(diào)用handleTap3和handleTap2(因為tap事件會冒泡到 middle view,而 middle view 阻止了 tap 事件冒泡,不再向父節(jié)點傳遞),點擊 middle view 會觸發(fā)handleTap2,點擊 outer view 會觸發(fā)handleTap1。
outer view
middle view
inner view
互斥事件綁定
自基礎(chǔ)庫版本 2.8.2 起,除 bind 和 catch 外,還可以使用 mut-bind 來綁定事件。一個 mut-bind 觸發(fā)后,如果事件冒泡到其他節(jié)點上,其他節(jié)點上的 mut-bind 綁定函數(shù)不會被觸發(fā),但 bind 綁定函數(shù)和 catch 綁定函數(shù)依舊會被觸發(fā)。
換而言之,所有 mut-bind 是“互斥”的,只會有其中一個綁定函數(shù)被觸發(fā)。同時,它完全不影響 bind 和 catch 的綁定效果。
例如在下邊這個例子中,點擊 inner view 會先后調(diào)用 handleTap3 和 handleTap2 ,點擊 middle view 會調(diào)用 handleTap2 和 handleTap1 。
outer view
middle view
inner view
事件的捕獲階段
自基礎(chǔ)庫版本 1.5.0 起,觸摸類事件支持捕獲階段。捕獲階段位于冒泡階段之前,且在捕獲階段中,事件到達(dá)節(jié)點的順序與冒泡階段恰好相反。需要在捕獲階段監(jiān)聽事件時,可以采用capture-bind、capture-catch關(guān)鍵字,后者將中斷捕獲階段和取消冒泡階段。
在下面的代碼中,點擊 inner view 會先后調(diào)用handleTap2、handleTap4、handleTap3、handleTap1。
outer view
inner view
如果將上面代碼中的第一個capture-bind改為capture-catch,將只觸發(fā)handleTap2。
outer view
inner view
事件對象
如無特殊說明,當(dāng)組件觸發(fā)事件時,邏輯層綁定該事件的處理函數(shù)會收到一個事件對象。
BaseEvent 基礎(chǔ)事件對象屬性列表:
| 屬性 | 類型 | 說明 | 基礎(chǔ)庫版本 |
|---|---|---|---|
| type | String | 事件類型 | |
| timeStamp | Integer | 事件生成時的時間戳 | |
| target | Object | 觸發(fā)事件的組件的一些屬性值集合 | |
| currentTarget | Object | 當(dāng)前組件的一些屬性值集合 | |
| mark | Object | 事件標(biāo)記數(shù)據(jù) | 2.7.1 |
CustomEvent 自定義事件對象屬性列表(繼承 BaseEvent):
| 屬性 | 類型 | 說明 |
|---|---|---|
| detail | Object | 額外的信息 |
TouchEvent 觸摸事件對象屬性列表(繼承 BaseEvent):
| 屬性 | 類型 | 說明 |
|---|---|---|
| touches | Array | 觸摸事件,當(dāng)前停留在屏幕中的觸摸點信息的數(shù)組 |
| changedTouches | Array | 觸摸事件,當(dāng)前變化的觸摸點信息的數(shù)組 |
特殊事件: canvas 中的觸摸事件不可冒泡,所以沒有 currentTarget。
type
代表事件的類型。
timeStamp
頁面打開到觸發(fā)事件所經(jīng)過的毫秒數(shù)。
target
觸發(fā)事件的源組件。
| 屬性 | 類型 | 說明 |
|---|---|---|
| id | String | 事件源組件的id |
| dataset | Object | 事件源組件上由data-開頭的自定義屬性組成的集合 |
currentTarget
事件綁定的當(dāng)前組件。
| 屬性 | 類型 | 說明 |
|---|---|---|
| id | String | 當(dāng)前組件的id |
| dataset | Object | 當(dāng)前組件上由data-開頭的自定義屬性組成的集合 |
說明: target 和 currentTarget 可以參考上例中,點擊 inner view 時,handleTap3 收到的事件對象 target 和 currentTarget 都是 inner,而 handleTap2 收到的事件對象 target 就是 inner,currentTarget 就是 middle。
dataset
在組件節(jié)點中可以附加一些自定義數(shù)據(jù)。這樣,在事件中可以獲取這些自定義的節(jié)點數(shù)據(jù),用于事件的邏輯處理。
在 WXML 中,這些自定義數(shù)據(jù)以 data- 開頭,多個單詞由連字符 - 連接。這種寫法中,連字符寫法會轉(zhuǎn)換成駝峰寫法,而大寫字符會自動轉(zhuǎn)成小寫字符。如:
- data-element-type ,最終會呈現(xiàn)為 event.currentTarget.dataset.elementType ;
- data-elementType ,最終會呈現(xiàn)為 event.currentTarget.dataset.elementtype 。
示例:
DataSet Test
Page({
bindViewTap:function(event){
event.currentTarget.dataset.alphaBeta === 1 // - 會轉(zhuǎn)為駝峰寫法
event.currentTarget.dataset.alphabeta === 2 // 大寫會轉(zhuǎn)為小寫
}
})
mark
在基礎(chǔ)庫版本 2.7.1 以上,可以使用 mark 來識別具體觸發(fā)事件的 target 節(jié)點。此外, mark 還可以用于承載一些自定義數(shù)據(jù)(類似于 dataset )。
當(dāng)事件觸發(fā)時,事件冒泡路徑上所有的 mark 會被合并,并返回給事件回調(diào)函數(shù)。(即使事件不是冒泡事件,也會 mark 。)
代碼示例:
在上述 WXML 中,如果按鈕被點擊,將觸發(fā) bindViewTap 和 bindButtonTap 兩個事件,事件攜帶的 event.mark 將包含 myMark 和 anotherMark 兩項。
Page({
bindViewTap: function(e) {
e.mark.myMark === "last" // true
e.mark.anotherMark === "leaf" // true
}
})
mark 和 dataset 很相似,主要區(qū)別在于: mark 會包含從觸發(fā)事件的節(jié)點到根節(jié)點上所有的 mark: 屬性值;而 dataset 僅包含一個節(jié)點的 data- 屬性值。
細(xì)節(jié)注意事項:
- 如果存在同名的 mark ,父節(jié)點的 mark 會被子節(jié)點覆蓋。
- 在自定義組件中接收事件時, mark 不包含自定義組件外的節(jié)點的 mark 。
- 不同于 dataset ,節(jié)點的 mark 不會做連字符和大小寫轉(zhuǎn)換。
touches
touches 是一個數(shù)組,每個元素為一個 Touch 對象(canvas 觸摸事件中攜帶的 touches 是 CanvasTouch 數(shù)組)。 表示當(dāng)前停留在屏幕上的觸摸點。
Touch 對象
| 屬性 | 類型 | 說明 |
|---|---|---|
| identifier | Number | 觸摸點的標(biāo)識符 |
| pageX, pageY | Number | 距離文檔左上角的距離,文檔的左上角為原點 ,橫向為X軸,縱向為Y軸 |
| clientX, clientY | Number | 距離頁面可顯示區(qū)域(屏幕除去導(dǎo)航條)左上角距離,橫向為X軸,縱向為Y軸 |
CanvasTouch 對象
| 屬性 | 類型 | 說明 | 特殊說明 |
|---|---|---|---|
| identifier | Number | 觸摸點的標(biāo)識符 | |
| x, y | Number | 距離 Canvas 左上角的距離,Canvas 的左上角為原點 ,橫向為X軸,縱向為Y軸 |
changedTouches
changedTouches 數(shù)據(jù)格式同 touches。 表示有變化的觸摸點,如從無變有(touchstart),位置變化(touchmove),從有變無(touchend、touchcancel)。
detail
自定義事件所攜帶的數(shù)據(jù),如表單組件的提交事件會攜帶用戶的輸入,媒體的錯誤事件會攜帶錯誤信息,詳見組件定義中各個事件的定義。
點擊事件的detail 帶有的 x, y 同 pageX, pageY 代表距離文檔左上角的距離。
WXS響應(yīng)事件
基礎(chǔ)庫 2.4.4 開始支持,低版本需做 兼容處理。
背景
有頻繁用戶交互的效果在小程序上表現(xiàn)是比較卡頓的,例如頁面有 2 個元素 A 和 B,用戶在 A 上做 touchmove 手勢,要求 B 也跟隨移動,movable-view 就是一個典型的例子。一次 touchmove 事件的響應(yīng)過程為:
a、touchmove 事件從視圖層(Webview)拋到邏輯層(App Service)
b、邏輯層(App Service)處理 touchmove 事件,再通過 setData 來改變 B 的位置
一次 touchmove 的響應(yīng)需要經(jīng)過 2 次的邏輯層和渲染層的通信以及一次渲染,通信的耗時比較大。此外 setData 渲染也會阻塞其它腳本執(zhí)行,導(dǎo)致了整個用戶交互的動畫過程會有延遲。
實現(xiàn)方案
本方案基本的思路是減少通信的次數(shù),讓事件在視圖層(Webview)響應(yīng)。小程序的框架分為視圖層(Webview)和邏輯層(App Service),這樣分層的目的是管控,開發(fā)者的代碼只能運行在邏輯層(App Service),而這個思路就必須要讓開發(fā)者的代碼運行在視圖層(Webview),如下圖所示的流程:
使用 WXS 函數(shù)用來響應(yīng)小程序事件,目前只能響應(yīng)內(nèi)置組件的事件,不支持自定義組件事件。WXS 函數(shù)的除了純邏輯的運算,還可以通過封裝好的ComponentDescriptor 實例來訪問以及設(shè)置組件的 class 和樣式,對于交互動畫,設(shè)置 style 和 class 足夠了。WXS 函數(shù)的例子如下:
var wxsFunction = function(event, ownerInstance) {
var instance = ownerInstance.selectComponent('.classSelector') // 返回組件的實例
instance.setStyle({
"font-size": "14px" // 支持rpx
})
instance.getDataset()
instance.setClass(className)
// ...
return false // 不往上冒泡,相當(dāng)于調(diào)用了同時調(diào)用了stopPropagation和preventDefault
}
其中入?yún)?nbsp;event 是小程序事件對象基礎(chǔ)上多了 event.instance 來表示觸發(fā)事件的組件的 ComponentDescriptor 實例。ownerInstance 表示的是觸發(fā)事件的組件所在的組件的 ComponentDescriptor 實例,如果觸發(fā)事件的組件是在頁面內(nèi)的,ownerInstance 表示的是頁面實例。
ComponentDescriptor的定義如下:
| 方法 | 參數(shù) | 描述 | 最低版本 |
|---|---|---|---|
| selectComponent | selector對象 | 返回組件的 ComponentDescriptor 實例。 | |
| selectAllComponents | selector對象數(shù)組 | 返回組件的 ComponentDescriptor 實例數(shù)組。 | |
| setStyle | Object/string | 設(shè)置組件樣式,支持rpx。設(shè)置的樣式優(yōu)先級比組件 wxml 里面定義的樣式高。不能設(shè)置最頂層頁面的樣式。 | |
| addClass/removeClass/ hasClass | string | 設(shè)置組件的 class。設(shè)置的 class 優(yōu)先級比組件 wxml 里面定義的 class 高。不能設(shè)置最頂層頁面的 class。 | |
| getDataset | 無 | 返回當(dāng)前組件/頁面的 dataset 對象 | |
| callMethod | (funcName:string, args:object) | 調(diào)用當(dāng)前組件/頁面在邏輯層(App Service)定義的函數(shù)。funcName表示函數(shù)名稱,args表示函數(shù)的參數(shù)。 | |
| requestAnimationFrame | Function | 和原生 requestAnimationFrame 一樣。用于設(shè)置動畫。 | |
| getState | 無 | 返回一個object對象,當(dāng)有局部變量需要存儲起來后續(xù)使用的時候用這個方法。 | |
| triggerEvent | (eventName, detail) | 和組件的triggerEvent一致。 | |
| getComputedStyle | Array. | 參數(shù)與 SelectorQuery 的 computedStyle 一致。 | 2.11.2 |
WXS 運行在視圖層(Webview),里面的邏輯畢竟能做的事件比較少,需要有一個機制和邏輯層(App Service)開發(fā)者的代碼通信,上面的 callMethod 是 WXS 里面調(diào)用邏輯層(App Service)開發(fā)者的代碼的方法,而 WxsPropObserver 是邏輯層(App Service)開發(fā)者的代碼調(diào)用 WXS 邏輯的機制。
使用方法
- WXML定義事件:
上面的change:prop(屬性前面帶change:前綴)是在 prop 屬性被設(shè)置的時候觸發(fā) WXS 函數(shù),值必須用{{}}括起來。類似 Component 定義的 properties 里面的 observer 屬性,在setData({propValue: newValue})調(diào)用之后會觸發(fā)。
注意:WXS函數(shù)必須用{{}}括起來。當(dāng) prop 的值被設(shè)置 WXS 函數(shù)就會觸發(fā),而不只是值發(fā)生改變,所以在頁面初始化的時候會調(diào)用一次WxsPropObserver的函數(shù)。
- WXS文件test.wxs里面定義并導(dǎo)出事件處理函數(shù)和屬性改變觸發(fā)的函數(shù):
module.exports = {
touchmove: function(event, instance) {
console.log('log event', JSON.stringify(event))
},
propObserver: function(newValue, oldValue, ownerInstance, instance) {
console.log('prop observer', newValue, oldValue)
}
}
提示:
- 目前還不支持原生組件的事件、input和textarea組件的 bindinput 事件
- 1.02.1901170及以后版本的開發(fā)者工具上支持交互動畫,最低版本基礎(chǔ)庫是2.4.4
- 目前在WXS函數(shù)里面僅支持console.log方式打日志定位問題,注意連續(xù)的重復(fù)日志會被過濾掉。
網(wǎng)站標(biāo)題:創(chuàng)新互聯(lián)小程序教程:微信小程序事件系統(tǒng)
文章來源:http://fisionsoft.com.cn/article/cdhihpd.html


咨詢
建站咨詢
