事件處理
一個應用僅僅只有界面展示是不夠的,還需要和用戶做交互,例如:響應用戶的點擊、獲取用戶輸入的值等等,在小程序里邊,我們就通過編寫 JS
腳本文件來處理用戶的操作
1. 事件綁定和事件對象
小程序中綁定事件與在網頁開發中綁定事件幾乎一致,只不過在小程序不能通過 on
的方式綁定事件,也沒有 click
等事件,小程序中綁定事件使用 bind
方法,click
事件也需要使用 tap
事件來進行代替,綁定事件的方式有兩種:
第一種方式:bind:事件名
,bind 后面需要跟上冒號,冒號后面跟上事件名
<button bind:tap="handler">按鈕</button>
第二種方式:bind事件名
,bind 后面直接跟上事件名
<button bindtap="handler">按鈕</button>
事件處理函數需要寫到 .js
文件中,在 .js
文件中需要調用小程序提供的 Page
方法來注冊小程序的頁面,我們可以直接在 Page
方法中創建事件處理函數。例如:
// pages/home/home.js
Page({// 頁面的初始數據data: {},// 事件處理程序handler () {console.log('我被執行啦~~~')}// 其他 coding...
})
當組件觸發事件時,綁定的事件的處理函數會收到一個事件對象,用來記錄事件發生時的相關信息。在觸發事件時,事件處理程序會主動的給我們傳入一個參數 —— event
(事件對象)
// pages/home/home.js
Page({// 頁面的初始數據data: {},// 事件處理程序handler (event) {// console.log('我被觸發了~~~')console.log(event)}// 其他 coding...
})
2. 綁定并阻止事件冒泡
事件分為冒泡事件和非冒泡事件:
- 冒泡事件:當一個組件上的事件被觸發后,該事件會向父節點傳遞。
- 非冒泡事件:當一個組件上的事件被觸發后,該事件不會向父節點傳遞。
使用 bind
綁定的事件,會觸發事件冒泡,如果想阻止事件冒泡,可以使用 catch
來綁定事件。
<view bindtap="parentHandler"><!-- 使用 bind 綁定的事件,會產生事件冒泡 --><!-- <button bindtap="handler">按鈕</button> --><!-- 使用 catcht 綁定的事件,會阻止事件冒泡 --><button catchtap="handler">按鈕</button>
</view>
Page({// 頁面的初始數據data: {},// 事件處理程序handler (event) {console.log('我是子綁定的事件 ~~~')},parentHandler () {console.log('我是父綁定的事件 ~~~')}// 其他 coding...
})
WXML
中冒泡事件列表如下表:
類型 | 觸發條件 |
---|---|
touchstart | 手指觸摸動作開始 |
touchmove | 手指觸摸后移動 |
touchcancel | 手指觸摸動作被打斷,如來電提醒,彈窗 |
touchend | 手指觸摸動作結束 |
tap | 手指觸摸后馬上離開 |
longpress | 手指觸摸后,超過350ms再離開,如果指定了事件回調函數并觸發了這個事件,tap事件將不被觸發 |
longtap | 手指觸摸后,超過350ms再離開(推薦使用 longpress 事件代替) |
transitionend | 會在 WXSS transition 或 wx.createAnimation 動畫結束后觸發 |
animationstart | 會在一個 WXSS animation 動畫開始時觸發 |
animationiteration | 會在一個 WXSS animation 一次迭代結束時觸發 |
animationend | 會在一個 WXSS animation 動畫完成時觸發 |
touchforcechange | 在支持 3D Touch 的 iPhone 設備,重按時會觸發 |
📌 注意事項:
? 除上表之外的其他組件自定義事件,如無特殊聲明都是非冒泡事件
? 例如 form 的submit
事件,input 的input
事件
3. 事件傳參-data-*自定義數據
在小程序中,可以通過事件傳參的方式,將數據傳遞給事件處理函數。常見的事件包括點擊事件、輸入事件等。
在組件節點中可以通過 data-
的方式傳遞一些自定義數據,傳遞的數據可以通過事件對象的方式進行獲取
📌 注意事項:
? 使用
data-
方法傳遞參數的時候,多個單詞由連字符-
連接? 連字符寫法會轉換成駝峰寫法,而大寫字符會自動轉成小寫字符
? 例如:
?
data-element-type
,最終會呈現為event.currentTarget.dataset.elementType
?
data-elementType
,最終會呈現為event.currentTarget.dataset.elementtype
在 wxml 文件中,使用 data-*
屬性將數據傳遞給事件處理函數。例如:
<view bindtap="parentHandler" data-parent-id="1" data-parentName="tom"><!-- 如果需要進行事件傳參,需要再組件上通過 data- 的方式傳遞數據 --><!-- <button bindtap="btnHandler" data-id="1" data-name="tom">按鈕</button> --><button data-id="1" data-name="tom">按鈕</button>
</view>
在 js 文件中,可以通過 event.currentTarget.dataset 獲取傳遞的數據
// cate.js
Page({// 按鈕觸發的事件處理函數btnHandler (event) {// currentTarget 事件綁定者,也就是指:哪個組件綁定了當前事件處理函數// target 事件觸發者,也就是指:哪個組件觸發了當前事件處理函數// currentTarget 和 target 都是指按鈕,因為是按鈕綁定的事件處理函數,同時點擊按鈕觸發事件處理函數// 這時候通過誰來獲取數據都可以console.log(event.currentTarget.dataset.id)console.log(event.target.dataset.name)},// view 綁定的事件處理函數parentHandler (event) {// 點擊藍色區域(不點擊按鈕)// currentTarget 事件綁定者:view// target 事件觸發者:view// currentTarget 和 target 都是指 view,如果想獲取 view 身上的數據,使用誰都可以// 點擊按鈕(不點擊藍色區域)// currentTarget 事件綁定者:view// target 事件觸發者:按鈕// 如果想獲取 view 身上的數據,就必須使用 currentTarget 才可以// 如果想獲取的是事件觸發者本身的數據,就需要使用 targetconsole.log(event)// 在傳遞參數的時候,如果自定義屬性是多個單詞,單詞與單詞直接使用中劃線 - 進行連接// 在事件對象中會被轉換為小托峰寫法console.log(event.currentTarget.dataset.parentId)// 在傳遞參數的時候,如果自定義屬性是多個單詞,單詞如果使用的是小托峰寫法// 在事件對象中會被轉為全部小寫的console.log(event.currentTarget.dataset.parentname)}})
4. 事件傳參-mark 自定義數據
小程序進行事件傳參的時候,除了使用 data-*
屬性傳遞參數外,還可以使用 mark
標記傳遞參數
mark
是一種自定義屬性,可以在組件上添加,用于來識別具體觸發事件的 target 節點。同時 mark
還可以用于承載一些自定義數據(類似于 dataset
)
mark
和 dataset
很相似,主要區別在于:
mark
會包含從觸發事件的節點到根節點上所有的 mark:
屬性值 (事件委托的)
dataset
僅包含觸發事件那一個節點的 data-
屬性值。
在 wxml 文件中,使用 mark:自定義屬性
的方式將數據傳遞給事件處理函數
<!-- pages/index/index.wxml --><view bindtap="parentHandler" mark:parentid="1" mark:parentname="tom"><!-- 如果需要使用 mark 進行事件傳參,需要使用 mark:自定義屬性的方式進行參數傳遞 --><!-- <button bindtap="btnHandler" mark:id="1" mark:name="tom">按鈕</button> --><button mark:id="1" mark:name="tom">按鈕</button>
</view>
// cart.js
Page({// 按鈕綁定的事件處理函數btnHandler (event) {console.log(event.mark.id)console.log(event.mark.name)},// view 綁定的事件處理函數parentHandler (event) {// 先點擊藍色區域 (不點擊按鈕)// 通過事件對象獲取的是 view 身上綁定的數據// 先點擊按鈕 (不點擊藍色區域)// 通過事件對象獲取到的是 觸發事件的節點 已經 父節點身上所有的 mark 數據console.log(event)}})