W3Cschool
恭喜您成為首批注冊用戶
獲得88經(jīng)驗值獎勵
如bindtap,當用戶點擊該組件的時候會在該頁面對應(yīng)的Page中找到相應(yīng)的事件處理函數(shù)。
<button id="tapTest" data-hi="WeChat" bindtap="tapName"> Click me! </button>
Page({
tapName: function(event) {
console.log(event)
}
})
{
"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
}]
}
基礎(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 module="wxs" src="./test.wxs"></wxs>
<view id="tapTest" data-hi="WeChat" bindtap="{{wxs.tapName}}"> Click me! </view>
**注:綁定的WXS函數(shù)必須用{{}}括起來**
function tapName(event, ownerInstance) {
console.log('tap wechat', JSON.stringify(event))
}
module.exports = {
tapName: tapName
}
ownerInstance包含了一些方法,可以設(shè)置組件的樣式和class,具體包含的方法以及為什么要用WXS函數(shù)響應(yīng)事件。
事件分為冒泡事件和非冒泡事件:
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事件,(詳見各個組件)
事件綁定的寫法類似于組件的屬性,如:
<view bindtap="handleTap">
Click here!
</view>
如果用戶點擊這個 view ,則頁面的 handleTap 會被調(diào)用。
事件綁定函數(shù)可以是一個數(shù)據(jù)綁定,如:
<view bindtap="{{ handlerName }}">
Click here!
</view>
此時,頁面的 this.data.handlerName 必須是一個字符串,指定事件處理函數(shù)名;如果它是個空字符串,則這個綁定會失效(可以利用這個特性來暫時禁用一些事件)。
自基礎(chǔ)庫版本 1.5.0 起,在大多數(shù)組件和自定義組件中, bind 后可以緊跟一個冒號,其含義不變,如 bind:tap 。基礎(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。
<view id="outer" bindtap="handleTap1">
outer view
<view id="middle" catchtap="handleTap2">
middle view
<view id="inner" bindtap="handleTap3">
inner view
</view>
</view>
</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 。
<view id="outer" mut-bind:tap="handleTap1">
outer view
<view id="middle" bindtap="handleTap2">
middle view
<view id="inner" mut-bind:tap="handleTap3">
inner view
</view>
</view>
</view>
自基礎(chǔ)庫版本 1.5.0 起,觸摸類事件支持捕獲階段。捕獲階段位于冒泡階段之前,且在捕獲階段中,事件到達節(jié)點的順序與冒泡階段恰好相反。需要在捕獲階段監(jiān)聽事件時,可以采用capture-bind、capture-catch關(guān)鍵字,后者將中斷捕獲階段和取消冒泡階段。
在下面的代碼中,點擊 inner view 會先后調(diào)用handleTap2、handleTap4、handleTap3、handleTap1。
<view id="outer" bind:touchstart="handleTap1" capture-bind:touchstart="handleTap2">
outer view
<view id="inner" bind:touchstart="handleTap3" capture-bind:touchstart="handleTap4">
inner view
</view>
</view>
如果將上面代碼中的第一個capture-bind改為capture-catch,將只觸發(fā)handleTap2。
<view id="outer" bind:touchstart="handleTap1" capture-catch:touchstart="handleTap2">
outer view
<view id="inner" bind:touchstart="handleTap3" capture-bind:touchstart="handleTap4">
inner view
</view>
</view>
如無特殊說明,當組件觸發(fā)事件時,邏輯層綁定該事件的處理函數(shù)會收到一個事件對象。
BaseEvent 基礎(chǔ)事件對象屬性列表:
屬性 | 類型 | 說明 | 基礎(chǔ)庫版本 |
---|---|---|---|
type | String | 事件類型 | |
timeStamp | Integer | 事件生成時的時間戳 | |
target | Object | 觸發(fā)事件的組件的一些屬性值集合 | |
currentTarget | Object | 當前組件的一些屬性值集合 | |
mark | Object | 事件標記數(shù)據(jù) | 2.7.1 |
CustomEvent 自定義事件對象屬性列表(繼承 BaseEvent):
屬性 | 類型 | 說明 |
---|---|---|
detail | Object | 額外的信息 |
TouchEvent 觸摸事件對象屬性列表(繼承 BaseEvent):
屬性 | 類型 | 說明 |
---|---|---|
touches | Array | 觸摸事件,當前停留在屏幕中的觸摸點信息的數(shù)組 |
changedTouches | Array | 觸摸事件,當前變化的觸摸點信息的數(shù)組 |
特殊事件: canvas 中的觸摸事件不可冒泡,所以沒有 currentTarget。
代表事件的類型。
頁面打開到觸發(fā)事件所經(jīng)過的毫秒數(shù)。
觸發(fā)事件的源組件。
屬性 | 類型 | 說明 |
---|---|---|
id | String | 事件源組件的id |
dataset | Object | 事件源組件上由data- 開頭的自定義屬性組成的集合 |
事件綁定的當前組件。
屬性 | 類型 | 說明 |
---|---|---|
id | String | 當前組件的id |
dataset | Object | 當前組件上由data- 開頭的自定義屬性組成的集合 |
說明: target 和 currentTarget 可以參考上例中,點擊 inner view 時,handleTap3 收到的事件對象 target 和 currentTarget 都是 inner,而 handleTap2 收到的事件對象 target 就是 inner,currentTarget 就是 middle。
在組件節(jié)點中可以附加一些自定義數(shù)據(jù)。這樣,在事件中可以獲取這些自定義的節(jié)點數(shù)據(jù),用于事件的邏輯處理。
在 WXML 中,這些自定義數(shù)據(jù)以 data- 開頭,多個單詞由連字符 - 連接。這種寫法中,連字符寫法會轉(zhuǎn)換成駝峰寫法,而大寫字符會自動轉(zhuǎn)成小寫字符。如:
示例:
<view data-alpha-beta="1" data-alphaBeta="2" bindtap="bindViewTap"> DataSet Test </view>
Page({
bindViewTap:function(event){
event.currentTarget.dataset.alphaBeta === 1 // - 會轉(zhuǎn)為駝峰寫法
event.currentTarget.dataset.alphabeta === 2 // 大寫會轉(zhuǎn)為小寫
}
})
在基礎(chǔ)庫版本 2.7.1 以上,可以使用 mark 來識別具體觸發(fā)事件的 target 節(jié)點。此外, mark 還可以用于承載一些自定義數(shù)據(jù)(類似于 dataset )。
當事件觸發(fā)時,事件冒泡路徑上所有的 mark 會被合并,并返回給事件回調(diào)函數(shù)。(即使事件不是冒泡事件,也會 mark 。)
代碼示例:
<view mark:myMark="last" bindtap="bindViewTap">
<button mark:anotherMark="leaf" bindtap="bindButtonTap">按鈕</button>
</view>
在上述 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- 屬性值。
細節(jié)注意事項:
touches 是一個數(shù)組,每個元素為一個 Touch 對象(canvas 觸摸事件中攜帶的 touches 是 CanvasTouch 數(shù)組)。 表示當前停留在屏幕上的觸摸點。
屬性 | 類型 | 說明 |
---|---|---|
identifier | Number | 觸摸點的標識符 |
pageX, pageY | Number | 距離文檔左上角的距離,文檔的左上角為原點 ,橫向為X軸,縱向為Y軸 |
clientX, clientY | Number | 距離頁面可顯示區(qū)域(屏幕除去導(dǎo)航條)左上角距離,橫向為X軸,縱向為Y軸 |
屬性 | 類型 | 說明 | 特殊說明 |
---|---|---|---|
identifier | Number | 觸摸點的標識符 | |
x, y | Number | 距離 Canvas 左上角的距離,Canvas 的左上角為原點 ,橫向為X軸,縱向為Y軸 |
changedTouches 數(shù)據(jù)格式同 touches。 表示有變化的觸摸點,如從無變有(touchstart),位置變化(touchmove),從有變無(touchend、touchcancel)。
自定義事件所攜帶的數(shù)據(jù),如表單組件的提交事件會攜帶用戶的輸入,媒體的錯誤事件會攜帶錯誤信息,詳見組件定義中各個事件的定義。
點擊事件的detail 帶有的 x, y 同 pageX, pageY 代表距離文檔左上角的距離。
基礎(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)致了整個用戶交互的動畫過程會有延遲。
本方案基本的思路是減少通信的次數(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 // 不往上冒泡,相當于調(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 | 無 | 返回當前組件/頁面的 dataset 對象 | |
callMethod | (funcName:string, args:object) | 調(diào)用當前組件/頁面在邏輯層(App Service)定義的函數(shù)。funcName表示函數(shù)名稱,args表示函數(shù)的參數(shù)。 | |
requestAnimationFrame | Function | 和原生 requestAnimationFrame 一樣。用于設(shè)置動畫。 |
|
getState | 無 | 返回一個object對象,當有局部變量需要存儲起來后續(xù)使用的時候用這個方法。 | |
triggerEvent | (eventName, detail) | 和組件的triggerEvent一致。 | |
getComputedStyle | Array.<string> | 參數(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 邏輯的機制。
<wxs module="test" src="./test.wxs"></wxs>
<view change:prop="{{test.propObserver}}" prop="{{propValue}}" bindtouchmove="{{test.touchmove}}" class="movable"></view>
上面的change:prop(屬性前面帶change:前綴)是在 prop 屬性被設(shè)置的時候觸發(fā) WXS 函數(shù),值必須用{{}}括起來。類似 Component 定義的 properties 里面的 observer 屬性,在setData({propValue: newValue})調(diào)用之后會觸發(fā)。
注意:WXS函數(shù)必須用{{}}括起來。當 prop 的值被設(shè)置 WXS 函數(shù)就會觸發(fā),而不只是值發(fā)生改變,所以在頁面初始化的時候會調(diào)用一次WxsPropObserver的函數(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)
}
}
Copyright©2021 w3cschool編程獅|閩ICP備15016281號-3|閩公網(wǎng)安備35020302033924號
違法和不良信息舉報電話:173-0602-2364|舉報郵箱:jubao@eeedong.com
掃描二維碼
下載編程獅App
編程獅公眾號
聯(lián)系方式:
更多建議: