# Respond to Events with WXS
Start from base library version 2.4.4. Please remaining backward compatible.
# Background
Frequent user interactions can cause stutters of a Mini Program. For example, A and B are two elements on the page. When the user makes a touchmove gesture on A, B is required to follow A to move. movable-view is a typical example. The response process for a touchmove event is as follows.
a. A touchmove event is thrown from the view layer (Webview) to the logical layer (App Service);
b. The touchmove event is handled at the logic layer (App Service), and then the position of B is changed through setData.
A response to touchmove involves two rounds of communication between the logic layer and rendering layer, as well as a rendering. The time-consumed communication and setData rendering that blocks the execution of other scripts cause delays of the interactive animations.
# Implementation of Solution
The solution is about reducing the number of communication rounds to respond to the event at the view layer (Webview). The framework of a Mini Program is divided into view layer (Webview) and logic layer (App Service) for better control. Developer's code can only run at the logic layer (Webview), but the solution requires that the code run at the view layer (App Service) instead, as shown below:
WXS function can only be used to respond to the events of built-in components of a Mini Program and does not support custom component events. In addition to purely logic operations, WXS function can also access and set the class and style of a component through the encapsulated ComponentDescriptor
instance. Setting style and class is sufficient for interactive animations. The following is an example of WXS function:
var wxsFunction = function(event, ownerInstance) {
var instance = ownerInstance.selectComponent('.classSelector') // Returns the instance of the component
instance.setStyle({
"font-size": "14px" // rpx is supported
})
instance.getDataset()
instance.setClass(className)
// ...
return false // The event does not bubble (is not propagated to the parent node), which means both stopPropagation and preventDefault are called.
}
For the input parameter event
, the event.instance
parameter is added to the event objects of Mini Program to indicate the ComponentDescriptor
instance of the component triggering the event. ownerInstance
represents the ComponentDescriptor
instance of the component where the component triggering the event resides. If the component triggering the event is inside the page, ownerInstance
indicates a page instance.
The definition of ComponentDescriptor
is as follows:
Method | Parameter | Description |
---|---|---|
selectComponent | "selector" object | Returns ComponentDescriptor instance of the component |
selectAllComponents | "selector" object array | Returns the array of ComponentDescriptor instances of the component |
setStyle | Object/string | Sets the component style (rpx is supported). The style set has priority over that defined in the component wxml. It does not support setting the style of the topmost page. |
addClass/removeClass/ hasClass | string | Sets the component class. The class set has priority over that defined in the component wxml. It does not support setting the class of the topmost page. |
getDataset | None | Returns the dataset object of the current component/page |
callMethod | (funcName:string, args:object) | Calls the function defined by the current component/page at the logic layer (App Service). funcName indicates the function name and args the function's parameters. |
requestAnimationFrame | Function | Sets animation, same as the native requestAnimationFrame . |
getState | None | Returns an object. It is used when a local variable needs to be stored for subsequent use. |
triggerEvent | (eventName, detail) | Same as triggerEvent of component |
WXS runs at the view layer (Webview), where fewer events can be handled. Therefore, a mechanism is needed to communicate with the developer's code at the logic layer (App Service). The callMethod
is a method in WXS that calls the developer's code at logic layer (App Service), and WxsPropObserver
is the mechanism by which the developer's code at logic layer (App Service) calls the WXS logic.
# Usage
- Define events using WXML
<wxs module="test" src="./test.wxs"></wxs>
<view change:prop="{{test.propObserver}}" prop="{{propValue}}" bindtouchmove="{{test.touchmove}}" class="movable"></view>
The change:prop
above (a property prefixed by change:) triggers the WXS function when the prop value is set, and its value must be enclosed with {{}}
. Similar to the "observer" in Component-defined properties, setData({propValue: newValue})
will trigger the WXS function once being called.
Note: The WXS function must be enclosed with {{}}
and is triggered once the prop value is set, rather than just when the value is changed. Therefore, the WxsPropObserver
function is called when the page is initialized.
- The event handler and the functions triggered when properties are changed are defined in and exported from the WXS file
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)
}
}
For more examples, see Preview with Developer Tool.
# Tips
- Events of native components and the bindinput event of input and textarea components are not supported.
- Weixin DevTools 1.02.1901170 or above supports interactive animations. The minimum version of base library is 2.4.4.
- Only console.log is supported for log location in the WXS function. Note that consecutive duplicate logs will be filtered out.