小程序框架之視圖層 View~事件系統~WXS響應事件


WXS響應事件

基礎庫 2.4.4 開始支持,低版本需做兼容處理

背景

有頻繁用戶交互的效果在小程序上表現是比較卡頓的,例如頁面有 2 個元素 A 和 B,用戶在 A 上做 touchmove 手勢,要求 B 也跟隨移動,movable-view 就是一個典型的例子。一次 touchmove 事件的響應過程為:

a、touchmove 事件從視圖層(Webview)拋到邏輯層(App Service)

b、邏輯層(App Service)處理 touchmove 事件,再通過 setData 來改變 B 的位置

一次 touchmove 的響應需要經過 2 次的邏輯層和渲染層的通信以及一次渲染,通信的耗時比較大。此外 setData 渲染也會阻塞其它腳本執行,導致了整個用戶交互的動畫過程會有延遲。

實現方案

本方案基本的思路是減少通信的次數,讓事件在視圖層(Webview)響應。小程序的框架分為視圖層(Webview)和邏輯層(App Service),這樣分層的目的是管控,開發者的代碼只能運行在邏輯層(App Service),而這個思路就必須要讓開發者的代碼運行在視圖層(Webview),如下圖所示的流程:

使用 WXS 函數用來響應小程序事件,目前只能響應內置組件的事件,不支持自定義組件事件。WXS 函數的除了純邏輯的運算,還可以通過封裝好的ComponentDescriptor 實例來訪問以及設置組件的 class 和樣式,對於交互動畫,設置 style 和 class 足夠了。WXS 函數的例子如下:

var wxsFunction = function(event, ownerInstance) { var instance = ownerInstance.selectComponent('.classSelector') // 返回組件的實例 instance.setStyle({ "font-size": "14px" // 支持rpx }) instance.getDataset() instance.setClass(className) // ... return false // 不往上冒泡,相當於調用了同時調用了stopPropagation和preventDefault } 

其中入參 event 是小程序事件對象基礎上多了 event.instance 來表示觸發事件的組件的 ComponentDescriptor 實例。ownerInstance 表示的是觸發事件的組件所在的組件的 ComponentDescriptor 實例,如果觸發事件的組件是在頁面內的,ownerInstance 表示的是頁面實例。

ComponentDescriptor的定義如下:

方法 參數 描述
selectComponent selector對象 返回組件的 ComponentDescriptor 實例。
selectAllComponents selector對象數組 返回組件的 ComponentDescriptor 實例數組。
setStyle Object/string 設置組件樣式,支持rpx。設置的樣式優先級比組件 wxml 里面定義的樣式高。不能設置最頂層頁面的樣式。
addClass/removeClass/ hasClass string 設置組件的 class。設置的 class 優先級比組件 wxml 里面定義的 class 高。不能設置最頂層頁面的 class。
getDataset 返回當前組件/頁面的 dataset 對象
callMethod (funcName:string, args:object) 調用當前組件/頁面在邏輯層(App Service)定義的函數。funcName表示函數名稱,args表示函數的參數。
requestAnimationFrame Function 和原生 requestAnimationFrame 一樣。用於設置動畫。
getState 返回一個object對象,當有局部變量需要存儲起來后續使用的時候用這個方法。
triggerEvent (eventName, detail) 和組件的triggerEvent一致。

WXS 運行在視圖層(Webview),里面的邏輯畢竟能做的事件比較少,需要有一個機制和邏輯層(App Service)開發者的代碼通信,上面的 callMethod 是 WXS 里面調用邏輯層(App Service)開發者的代碼的方法,而 WxsPropObserver 是邏輯層(App Service)開發者的代碼調用 WXS 邏輯的機制。

使用方法

  • WXML定義事件:
<wxs module="test" src="./test.wxs"></wxs> <view change:prop="{{test.propObserver}}" prop="{{propValue}}" bindtouchmove="{{test.touchmove}}" class="movable"></view> 

上面的change:prop(屬性前面帶change:前綴)是在 prop 屬性被設置的時候觸發 WXS 函數,值必須用{{}}括起來。類似 Component 定義的 properties 里面的 observer 屬性,在setData({propValue: newValue})調用之后會觸發。

注意:WXS函數必須用{{}}括起來。當 prop 的值被設置 WXS 函數就會觸發,而不只是值發生改變,所以在頁面初始化的時候會調用一次WxsPropObserver的函數。

  • WXS文件test.wxs里面定義並導出事件處理函數和屬性改變觸發的函數:
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)
    }
}

更多示例請查看在開發者工具中預覽效果

Tips

  1. 目前還不支持原生組件的事件、inputtextarea組件的 bindinput 事件
  2. 1.02.1901170及以后版本的開發者工具上支持交互動畫,最低版本基礎庫是2.4.4
  3. 目前在WXS函數里面僅支持console.log方式打日志定位問題,注意連續的重復日志會被過濾掉。

 

 

 

 

 

.


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM