1. 程式人生 > >微信小程式事件繫結

微信小程式事件繫結

![](https://imgconvert.csdnimg.cn/aHR0cHM6Ly9wMy1qdWVqaW4uYnl0ZWltZy5jb20vdG9zLWNuLWktazN1MWZicGZjcC9lNmQxZjc1NjlmOTY0Yjk2OGRlNWE0YjE3ZDI1MDU2Yn50cGx2LWszdTFmYnBmY3Atem9vbS0xLmltYWdl?x-oss-process=image/format,png) # 一 通過例項來認識 ## (一) 給出程式碼 我們直接通過一個例項來引入我們想要講解的內容: ```html ``` 上述程式碼就四行,首先是一個 input 輸入框,目的是用來輸入一些值,同時下面標籤就會顯示,接著是兩個 button 用來分別執行 +1 或者 -1 的操作,最後一個 view 標籤就是為了 進行資料輸入或變化的回顯 ```js 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 - 需要使用: ```js 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 則可以使用如下的方式,先把事件打印出來 ```js handleInput(e){ console.log(e); }, ``` 在找到對應的層級 ![](https://imgconvert.csdnimg.cn/aHR0cHM6Ly9wMy1qdWVqaW4uYnl0ZWltZy5jb20vdG9zLWNuLWktazN1MWZicGZjcC9iNTRiODVmYmU3ZmY0YzFhYmI4NGRmNDI2M2FjMDk5YX50cGx2LWszdTFmYnBmY3Atem9vbS0xLmltYWdl?x-oss-process=image/format,png) # 二 事件繫結類別 ## (一) 分類 我們上面的例子使用了 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](https://developers.weixin.qq.com/miniprogram/dev/framework/compatibility.html) | | longtap | 手指觸控後,超過350ms再離開(推薦使用longpress事件代替) | | | transitionend | 會在 WXSS transition 或 wx.createAnimation 動畫結束後觸發 | | | animationstart | 會在一個 WXSS animation 動畫開始時觸發 | | | animationiteration | 會在一個 WXSS animation 一次迭代結束時觸發 | | | animationend | 會在一個 WXSS animation 動畫完成時觸發 | | | touchforcechange | 在支援 3D Touch 的 iPhone 裝置,重按時會觸發 | [1.9.90](https://developers.weixin.qq.com/miniprogram/dev/framework/compatibility.html) | > 注:除上表之外的其他元件自定義事件如無特殊宣告都是非冒泡事件,如 form 的submit事件,input 的input事件,scroll-view 的scroll事件,(詳見各個元件) 看完上面的表格,應該就比較清楚了,正因為我們很多事件都是通過手機點一下某個元件等進行,所以 tap 是比較常用的 ## (三) bind 和 catch 說明:程式碼在下面自取 ### (1) bind 前面我們提到了,使用 bind 會發生冒泡事件,我們來模擬一下 首先我們寫了三個巢狀的 view 標籤,然後接著使用 bindtap 進行事件繫結,進行一個基本的列印邏輯,看看會有什麼情況發生 ![](https://imgconvert.csdnimg.cn/aHR0cHM6Ly9wMy1qdWVqaW4uYnl0ZWltZy5jb20vdG9zLWNuLWktazN1MWZicGZjcC9hY2Y5YTIwZmU0ODY0MWU2YjczMjhmNDM3N2Y0MThkYX50cGx2LWszdTFmYnBmY3Atem9vbS0xLmltYWdl?x-oss-process=image/format,png) 當點選中間層後,首先執行了中間層的事件效果,但是最外層的事件效果也被執行了,這也就是冒泡事件發生了 ![](https://imgconvert.csdnimg.cn/aHR0cHM6Ly9wMy1qdWVqaW4uYnl0ZWltZy5jb20vdG9zLWNuLWktazN1MWZicGZjcC85ZTE5OWQ3N2YwNjI0NDBiYjFjODNlYzI4NjAxOTFjYn50cGx2LWszdTFmYnBmY3Atem9vbS0xLmltYWdl?x-oss-process=image/format,png) > **冒泡事件**:當一個元件上的事件被觸發後,該事件會向父節點傳遞 > > **非冒泡事件**:當一個元件上的事件被觸發後,該事件不會向父節點傳遞 ### (3) catch 這一次我們仍然點選中間這一層,如果在上面的基礎上,我們將中間層的事件繫結使用 catch,而不是 bind ,結果會是怎樣呢? ![](https://imgconvert.csdnimg.cn/aHR0cHM6Ly9wMy1qdWVqaW4uYnl0ZWltZy5jb20vdG9zLWNuLWktazN1MWZicGZjcC84NDM1MDYxNTk0YjE0YjcyYjI3ODQyM2ZkYzJjMDY3ZH50cGx2LWszdTFmYnBmY3Atem9vbS0xLmltYWdl?x-oss-process=image/format,png) 結果就是冒泡事件被阻止了,點選後只顯示中間層的事件 ## (四) capture-bind 和 capture-catch 前面提及到這兩個內容的時候,我們提到了一個概念也就是事件的捕獲階段,簡單說一下: > 自基礎庫版本 1.5.0 起,觸控類事件支援捕獲階段。捕獲階段位於冒泡階段之前,且在捕獲階段中,事件到達節點的順序與冒泡階段恰好相反。需要在捕獲階段監聽事件時,可以採用capture-bind、capture-catch關鍵字,後者將中斷捕獲階段和取消冒泡階段。 ### (1) capture-bind:tap 依舊是剛才的例子,將三層的屬性都修改為 `capture-bind:tap="handleTap1"` 這種形式的 當我們點選最裡層的內容時,執行結果如下: ![](https://imgconvert.csdnimg.cn/aHR0cHM6Ly9wMy1qdWVqaW4uYnl0ZWltZy5jb20vdG9zLWNuLWktazN1MWZicGZjcC9jMGM4MGEzNjI0NjM0MTBhYjA0ZjE0YWU5NTlhOTIzNX50cGx2LWszdTFmYnBmY3Atem9vbS0xLmltYWdl?x-oss-process=image/format,png) 即它與包裹它的兩層都執行了,且是從外至內 ### (2) capture-catch:tap 將三層屬性修改為 `capture-catch:tap="handleTap1"` 這種形式,點選任意一層: ![](https://imgconvert.csdnimg.cn/aHR0cHM6Ly9wMy1qdWVqaW4uYnl0ZWltZy5jb20vdG9zLWNuLWktazN1MWZicGZjcC8xYTcwMDZiMDI3YTU0ODVmOWU4Njc3MTZjYzdhYjA2N350cGx2LWszdTFmYnBmY3Atem9vbS0xLmltYWdl?x-oss-process=image/format,png) 結果都是隻執行最外層的 ## (五) 簡單總結 - **bind**:點選會觸發它和包裹它的所有事件,且從內向外執行(冒泡事件) - **catch**:點選哪個就觸發哪個,獨立的(阻止冒泡事件) - **capture-bind**: 點選會觸發它和包裹它的所有事件,且從外向內執行 - **capture-catch**:如何點選都只會觸發最外層的事件 ## (六) 程式碼提取 程式碼給出的是 capture-bind:tap 的情況, bindtap 或者 catchtap 以及 capture-catch 只需要將 capture-bind:tap 替換就行了 **wxml** ```html ``` **wxss** ```css .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; } ``` # 結尾 如果文章中有什麼不足,歡迎大家留言交流,感謝朋友們的支援! 如果能幫到你的話,那就來關注我吧!如果您更喜歡微信文章的閱讀方式,可以關注我的公眾號 > 在這裡的我們素不相識,卻都在為了自己的夢而努力 ❤ > > 一個堅持推送原創開發技術文章的公眾號:理想二旬不止 ![](https://imgconvert.csdnimg.cn/aHR0cHM6Ly9wMy1qdWVqaW4uYnl0ZWltZy5jb20vdG9zLWNuLWktazN1MWZicGZjcC9iNGU4ZDIzNTk2NzA0NGY4YmQ3NzY3ZTZhNTQ3OTVmYX50cGx2LWszdTFmYnBmY3Atem9vbS0xLmltYWdl?x-oss-process=image/form