一 通過例項來認識
(一) 給出程式碼
我們直接通過一個例項來引入我們想要講解的內容:
<input type="text" bindinput="handleInput" />
<button bindtap="handletap" data-operation="{{1}}">+</button>
<button bindtap="handletap" data-operation="{{-1}}">-</button>
<view>你輸入的是:{{number}}</view>
上述程式碼就四行,首先是一個 input 輸入框,目的是用來輸入一些值,同時下面標籤就會顯示,接著是兩個 button 用來分別執行 +1 或者 -1 的操作,最後一個 view 標籤就是為了 進行資料輸入或變化的回顯
Page({
data: {
number:0
},
handleInput(e){
this.setData({
number:e.detail.value
})
},
handletap(e){
const operation = e.currentTarget.dataset.operation
this.setData({
number:this.data.number + operation
// number:this.data.number * 1 + e.currentTarget.dataset.operation
})
}
})
這裡給出的就是對應的 js 程式碼,涉及到了對於輸入以及 +1 或者 -1 操作的一個具體邏輯處理,核心就是圍繞 data 中定義的 number 變數進行處理(具體邏輯接著會提到),結合前面的 wxml 程式碼分析一下:
(二) 分析程式碼
分析標籤中屬性中的部分:
bindinput="handleInput"
bindtap="handletap" data-operation="{{-1}}"
- 繫結事件的關鍵字是
bind
例如上面用到的bindinput
和bindtap
就是分別對於輸入和點選事件的一個繫結 - 而後面的一個名稱例如 handleInput 就是自定義的事件名稱,我們在 js 中書寫方法也是與這個後面的名稱相對應
- 注:繫結關鍵字為 bind 僅針對此例,並非只是 bind
補充幾個 input 中相對常用的事件繫結屬性
屬性 | 型別 | 必填 | 說明 | 最低版本 |
---|---|---|---|---|
bindinput | eventhandle | 是 | 鍵盤輸入時觸發,event.detail = {value, cursor, keyCode},keyCode 為鍵值,2.1.0 起支援,處理函式可以直接 return 一個字串,將替換輸入框的內容。 | 1.0.0 |
bindfocus | eventhandle | 是 | 輸入框聚焦時觸發,event.detail = { value, height },height 為鍵盤高度,在基礎庫 1.9.90 起支援 | 1.0.0 |
bindblur | eventhandle | 是 | 輸入框失去焦點時觸發,event.detail = {value: value} |
如果想要獲取到輸入框的值,通過時間源物件來獲取 e.detail.value
(1) JS 中賦值問題
輸入框中輸入的值賦值給 data 中的 number,如果按慣性思維直接賦值是有問題的
-
不能使用 this.data.numer = e.detail.value
-
不能使用 this.number = e.detail.value
-
需要使用:
this.setData({
number:e.detail.value
})
(2) JS 中按鈕傳參問題
新增按鈕點選事件:關鍵字是 bindtap
我們按鈕想要達到的目的是,點選按鈕進行 number 的 +1 或者 -1 ,通過根據我們上面的 js 程式碼可以看出,這裡所採用實現的方式是根據頁面屬性中傳來的引數,進行相加,例如 number + 1 或者 number + (-1) 達到加減效果
但是,直接傳參是有問題的!!!只能通過屬性賦值
正解:bindtap="handletap" data-operation="{{-1}}"
(3) 忘記想要的值對應在哪裡
說明:如果記不住例如:e.detail.value、e.currentTarget.dataset.operation 則可以使用如下的方式,先把事件列印出來
handleInput(e){
console.log(e);
},
在找到對應的層級
二 事件繫結類別
(一) 分類
我們上面的例子使用了 bind 這個事件繫結關鍵字,但是它會發生冒泡事件
-
冒泡事件:當一個元件上的事件被觸發後,該事件會向父節點傳遞
-
非冒泡事件:當一個元件上的事件被觸發後,該事件不會向父節點傳遞
我們還有一些別的選擇,我們下面在 (3) (4) 中會一個一個進行分析
- bind:普通繫結(會發生冒泡事件)
- catch:可以阻止事件冒泡
- capture-bind: 捕獲階段繫結(後面的捕獲流程和冒泡流程還會繼續執行)
- capture-catch:中斷捕獲階段和取消冒泡階段,在捕獲階段阻止事件的傳遞
(二) 冒泡事件列表
在分析前,我們還要補充一個點,那就是 WXML 的冒泡事件列表:
我們起碼現在知道了 bind 和 catch 的作用,但是正例如我們上面用到的 bindinput 或者 bindtap ,bind 後面的內容又是什麼呢?是固定的還是自定義的呢?這一段我直接貼一段官網的文件說明
型別 | 觸發條件 | 最低版本 |
---|---|---|
touchstart | 手指觸控動作開始 | |
touchmove | 手指觸控後移動 | |
touchcancel | 手指觸控動作被打斷,如來電提醒,彈窗 | |
touchend | 手指觸控動作結束 | |
tap | 手指觸控後馬上離開 | |
longpress | 手指觸控後,超過350ms再離開,如果指定了事件回撥函式並觸發了這個事件,tap事件將不被觸發 | 1.5.0 |
longtap | 手指觸控後,超過350ms再離開(推薦使用longpress事件代替) | |
transitionend | 會在 WXSS transition 或 wx.createAnimation 動畫結束後觸發 | |
animationstart | 會在一個 WXSS animation 動畫開始時觸發 | |
animationiteration | 會在一個 WXSS animation 一次迭代結束時觸發 | |
animationend | 會在一個 WXSS animation 動畫完成時觸發 | |
touchforcechange | 在支援 3D Touch 的 iPhone 裝置,重按時會觸發 | 1.9.90 |
注:除上表之外的其他元件自定義事件如無特殊宣告都是非冒泡事件,如 form 的submit事件,input 的input事件,scroll-view 的scroll事件,(詳見各個元件)
看完上面的表格,應該就比較清楚了,正因為我們很多事件都是通過手機點一下某個元件等進行,所以 tap 是比較常用的
(三) bind 和 catch
說明:程式碼在下面自取
(1) bind
前面我們提到了,使用 bind 會發生冒泡事件,我們來模擬一下
首先我們寫了三個巢狀的 view 標籤,然後接著使用 bindtap 進行事件繫結,進行一個基本的列印邏輯,看看會有什麼情況發生
當點選中間層後,首先執行了中間層的事件效果,但是最外層的事件效果也被執行了,這也就是冒泡事件發生了
冒泡事件:當一個元件上的事件被觸發後,該事件會向父節點傳遞
非冒泡事件:當一個元件上的事件被觸發後,該事件不會向父節點傳遞
(3) catch
這一次我們仍然點選中間這一層,如果在上面的基礎上,我們將中間層的事件繫結使用 catch,而不是 bind ,結果會是怎樣呢?
結果就是冒泡事件被阻止了,點選後只顯示中間層的事件
(四) capture-bind 和 capture-catch
前面提及到這兩個內容的時候,我們提到了一個概念也就是事件的捕獲階段,簡單說一下:
自基礎庫版本 1.5.0 起,觸控類事件支援捕獲階段。捕獲階段位於冒泡階段之前,且在捕獲階段中,事件到達節點的順序與冒泡階段恰好相反。需要在捕獲階段監聽事件時,可以採用capture-bind、capture-catch關鍵字,後者將中斷捕獲階段和取消冒泡階段。
(1) capture-bind:tap
依舊是剛才的例子,將三層的屬性都修改為 capture-bind:tap="handleTap1"
這種形式的
當我們點選最裡層的內容時,執行結果如下:
即它與包裹它的兩層都執行了,且是從外至內
(2) capture-catch:tap
將三層屬性修改為 capture-catch:tap="handleTap1"
這種形式,點選任意一層:
結果都是隻執行最外層的
(五) 簡單總結
- bind:點選會觸發它和包裹它的所有事件,且從內向外執行(冒泡事件)
- catch:點選哪個就觸發哪個,獨立的(阻止冒泡事件)
- capture-bind: 點選會觸發它和包裹它的所有事件,且從外向內執行
- capture-catch:如何點選都只會觸發最外層的事件
(六) 程式碼提取
程式碼給出的是 capture-bind:tap 的情況, bindtap 或者 catchtap 以及 capture-catch 只需要將 capture-bind:tap 替換就行了
wxml
<view class="outer" capture-bind:tap="handleTap1">
這是最外層
<view class="middle" capture-bind:tap="handleTap2">
這是中間層
<view class="inner" capture-bind:tap="handleTap3">
這是最裡層
</view>
</view>
</view>
wxss
.outer {
text-align: center;
background-color: red;
height: 300rpx;
}
.middle {
background-color: orange;
width: 60%;
height: 200rpx;
}
.inner {
background-color: yellow;
width: 60%;
height: 100rpx;
}
結尾
如果文章中有什麼不足,歡迎大家留言交流,感謝朋友們的支援!
如果能幫到你的話,那就來關注我吧!如果您更喜歡微信文章的閱讀方式,可以關注我的公眾號
在這裡的我們素不相識,卻都在為了自己的夢而努力 ❤
一個堅持推送原創開發技術文章的公眾號:理想二旬不止
e