Coding With Fun
Home Docker Django Node.js Articles Python pip guide FAQ Policy

WeChat small program event system


May 17, 2021 WeChat Mini Program Development Document


Table of contents


Event

What is an event

  • Events are how the view layer communicates to the logical layer.
  • Events can feedback the user's behavior to the logical layer for processing.
  • Events can be bound to a component, and when a trigger event is reached, the corresponding event handler in the logical layer is executed.
  • Event objects can carry additional information such as id, dataset, touches.

How events are used

  • Bind an event handler in a component.

For example, bindtap, when the user clicks on the component, the appropriate event handler is found in page on the page.

<view id="tapTest" data-hi="WeChat" bindtap="tapName"> Click me! </view>
  • Write the appropriate event handler in the corresponding Page definition, and the argument is event.
Page({
  tapName: function(event) {
    console.log(event)
  }
})
  • You can see that the information from the log is roughly as follows:
{
  "type":"tap",
  "timeStamp":895,
  "target": {
    "id": "tapTest",
    "dataset":  {
      "hi":"WeChat"
    }
  },
  "currentTarget":  {
    "id": "tapTest",
    "dataset": {
      "hi":"WeChat"
    }
  },
  "detail": {
    "x":53,
    "y":14
  },
  "touches":[{
    "identifier":0,
    "pageX":53,
    "pageY":14,
    "clientX":53,
    "clientY":14
  }],
  "changedTouches":[{
    "identifier":0,
    "pageX":53,
    "pageY":14,
    "clientX":53,
    "clientY":14
  }]
}

Respond to events using the WXS function

Base Library 2.4.4 starts to support, and low versions need to be compatible.

Starting with the underlying library version 2.4.4, it is supported to bind events using the WXS function, which accepts 2 parameters, the first of which is the object, which adds the object.instance object on top of the original object, and the second argument, which is the enterpriseInstance, which, like the event.instance, is a CompanyDescriptor object. Here's how to use it:

  • The WXS function that binds and registers event handling in the component.
<wxs module="wxs" src="./test.wxs"></wxs>
<view id="tapTest" data-hi="WeChat" bindtap="{{wxs.tapName}}"> Click me! </view>
**注:绑定的WXS函数必须用{{}}括起来**

  • The test.wxs file implements the tapName function
function tapName(event, ownerInstance) {
  console.log('tap wechat', JSON.stringify(event))
}
module.exports = {
  tapName: tapName
}

OwnerInstance contains methods to style components and classes, including methods and why to respond to events with WXS functions.

The event is detailed

Event classification

Events are divided into bubbling events and non-bubble events:

  1. Bubble event: When an event on a component is triggered, the event is passed to the parent node.
  2. Non-bubble event: When an event on a component is triggered, the event is not passed to the parent node.

List of bubbling events for WXML:

Type The trigger condition The lowest version
touchstart The finger touch action begins
touchmove Move your finger when you touch it
touchcancel Finger touch movements are interrupted, such as a call alert, and a window is played
touchend The finger touch action ends
tap Leave as soon as your finger is touched
longpress After the finger is touched, more than 350ms leaves again, and if the event callback function is specified and the event is triggered, the tap event will not be triggered 1.5.0
longtap After finger touch, more than 350ms leave again (longpress events are recommended instead)
transitionend triggers after the WXSS transition or wx.createAnimation animation ends
animationstart is triggered at the beginning of a WXSS animation animation
animationiteration is triggered at the end of an iteration of WXSS animation
animationend is triggered when a WXSS animation animation is complete
touchforcechange On iPhone devices that support 3D Touch, re-time is triggered 1.9.90

Note: Other component custom events other than the table above, such as non-bubble events such as form submit events, input input events, scroll-view scroll events, (see components for details)

Normal event binding

Event bindings are written like the properties of a component, such as:

<view bindtap="handleTap">
    Click here!
</view>

If the user clicks on this view, the handleTap of the page is called.

An event binding function can be a data binding, such as:

<view bindtap="{{ handlerName }}">
    Click here!
</view>

At this point, the page's this.data.handlerName must be a string that specifies the name of the event handler;

Since underlying library version 1.5.0, in most components and custom components, bind can be followed by a colon with the same meaning, such as bind:tap. Starting with base library version 2.8.1, this support is available in all components.

Bind and prevent events from bubbling

In addition to bind, you can also bind events with catch. Unlike bind, catch prevents events from bubbling up.

For example, in the example between the inner view, handleTap3 and handleTap2 are called (because the tap event bubbles to middle view, and the middle view prevents the tap event from bubbling and no longer passes to the parent node), clicking middle view triggers handleTap2, and clicking outer view triggers handleTap1.

<view id="outer" bindtap="handleTap1">
  outer view
  <view id="middle" catchtap="handleTap2">
    middle view
    <view id="inner" bindtap="handleTap3">
      inner view
    </view>
  </view>
</view>

Mutually exclusive event binding

Since underlying library version 2.8.2, mut-bind can be used to bind events in addition to bind and catch. When a mut-bind is triggered, the mut-bind binding function on the other nodes is not triggered if the event bubbles to another node, but the bind binding function and catch binding function are still triggered.

In other words, all mut-binds are "mutually exclusive" and only one of the binding functions is triggered. At the same time, it does not affect the binding effect of bind and catch at all.

For example, in the example between the inner view, handleTap3 and handleTap2 are called, and the middle view is called handleTap2 and handleTap1.

<view id="outer" mut-bind:tap="handleTap1">
  outer view
  <view id="middle" bindtap="handleTap2">
    middle view
    <view id="inner" mut-bind:tap="handleTap3">
      inner view
    </view>
  </view>
</view>

The capture phase of the event

Touch class events support the capture phase since the underlying library version 1.5.0. T he capture phase is before the bubbling phase, and in the capture phase, the events reach the node in the exact opposite order to the bubbling phase. When you need to listen for events during the capture phase, you can use the capture-bind, capture-catch keywords, which interrupt the capture phase and cancel the bubbling phase.

In the following code, clicking inner view calls handleTap2, handleTap4, handleTap3, handleTap1.

<view id="outer" bind:touchstart="handleTap1" capture-bind:touchstart="handleTap2">
  outer view
  <view id="inner" bind:touchstart="handleTap3" capture-bind:touchstart="handleTap4">
    inner view
  </view>
</view>

If you change the first capture-bind in the code above to capture-catch, only handleTap2 will be triggered.

<view id="outer" bind:touchstart="handleTap1" capture-catch:touchstart="handleTap2">
  outer view
  <view id="inner" bind:touchstart="handleTap3" capture-bind:touchstart="handleTap4">
    inner view
  </view>
</view>

The event object

Without special instructions, when a component triggers an event, the handler of the logical layer binding the event receives an event object.

BaseEvent List of Underlying Event Object Properties:

Property Type Description The underlying library version
type String The type of event
timeStamp Integer The timestamp at the time the event was generated
target Object A collection of property values for the component that triggered the event
currentTarget Object A collection of some property values for the current component
mark Object Event tag data 2.7.1

CustomEvent Custom Event Object Properties List (Inherit BaseEvent):

Property Type Description
detail Object Additional information

TouchEvent Touch Event Object Properties List (Inherit BaseEvent):

Property Type Description
touches Array An array of touch-point information that currently stays on the screen
changedTouches Array An array of touch events, the currently changing touch point information

Special event: Touch events in canvas are not bubbling, so there is no currentTarget.

type

Represents the type of event.

timeStamp

The number of milliseconds from the page opening to triggering the event.

target

The source component that triggered the event.

Property Type Description
Id String The id of the event source component
dataset Object A collection of custom properties data- on the event source component

currentTarget

The current component of the event binding.

Property Type Description
Id String The id of the current component
dataset Object A collection of custom data- current component that begin with data-

Description: Target and currentTarget can refer to the example above, when clicking inner view, handleTap3 receives the event object target and currentTarget are both inner, while handleTap2 receives the event object target inner, currentTarget is middle.

dataset

Some custom data can be attached to the component node. This allows you to obtain these custom node data in the event for logical processing of the event.

In WXML, these custom data start with data- and multiple words are connected by a hyphen. I n this way of writing, hyphen writing is converted to hump writing, and capital characters are automatically converted to small-case characters. Such as:

  • data-element-type, which will eventually appear as event.currentTarget.dataset.elementType;
  • data-elementType, which will eventually appear as event.currentTarget.dataset.elementtype.

Example:

<view data-alpha-beta="1" data-alphaBeta="2" bindtap="bindViewTap"> DataSet Test </view>
Page({
  bindViewTap:function(event){
    event.currentTarget.dataset.alphaBeta === 1 // - 会转为驼峰写法
    event.currentTarget.dataset.alphabeta === 2 // 大写会转为小写
  }
})

mark

Above base library version 2.7.1, you can use mark to identify the target node that specifically triggered the event. In addition, mark can be used to host some custom data (similar to dataset).

When an event is triggered, all marks on the event bubble path are merged and returned to the event callback function. ( Even if the event is not a bubbling event, it will mark .)

Code example:

<view mark:myMark="last" bindtap="bindViewTap">
  <button mark:anotherMark="leaf" bindtap="bindButtonTap">按钮</button>
</view>

In WXML above, if the button is clicked, two events, bindViewTap and bindButtonTap, will be triggered, and event.mark carried by the event will contain both myMark and anotherMark.

Page({
  bindViewTap: function(e) {
    e.mark.myMark === "last" // true
    e.mark.anotherMark === "leaf" // true
  }
})

Mark is similar to dataset, the main difference being that mark contains all the mark: property values from the node that triggered the event to the root node, while dataset contains only one node's data-property value.

Details:

  • If there is a mark with the same name, the mark of the parent node is overwritten by the child node.
  • When you receive events in a custom component, mark does not contain the mark of nodes outside the custom component.
  • Unlike dataset, the node's mark does not make hyphens and case conversions.

touches

Touches is an array, each element is a Touch object (the touches that are carried in the canvas touch event are canvasTouch arrays). Represents the touch point that is currently stuck on the screen.

Touch object

Property Type Description
identifier Number The identifier of the touch point
pageX, pageY Number The distance from the upper-left corner of the document, the upper-left corner of the document is the origin, the landscape is the X-axis, and the portrait is the Y-axis
clientX, clientY Number Distance from the page shows the distance in the upper left corner of the area (screen removes the navigation bar), with the X-axis in the landscape and the Y-axis in portrait

CanvasTouch object

Property Type Description Special instructions
identifier Number The identifier of the touch point
x, y Number At the distance from the upper left corner of Canvas, the upper left corner of Canvas is the origin, the X-axis is horizontal, and the vertical is the Y-axis

changedTouches

ChangedTouches data format with touches. Represents a changed touch point, such as a touchstart, a touchmove, a touchmove, a touchend, touchcancel.

detail

Custom events carry data, such as the submission event for a form component that carries the user's input, and media error events that carry error messages, as detailed in the definition of each event in the component definition.

Clicking on the event's detail with x, y and pageX, pageY represents the distance from the upper left corner of the document.


WXS responds to events

Base Library 2.4.4 starts to support, and low versions need to be compatible.

Background

The effect of frequent user interaction on small programs is compared to Caton's, for example, the page has 2 elements A and B, the user does touchmove gestures on A, requires B to follow the movement, movable-view is a typical example. The response process for a touchmove event is:

a. Touchmove event throws from view layer to logical layer (App Service)

b. The Logic Layer (App Service) handles touchmove events and then changes B's position through setData

A touchmove response requires communication between the logical and render layers twice, as well as a rendering, which takes a lot of time. In addition, setData rendering blocks other script execution, causing delays in the animation process for the entire user interaction.

Implementation scenarios

The basic idea of this scenario is to reduce the number of communications and have events respond at the view level. The framework of a small program is divided into a view layer (Webview) and a logical layer (App Service), so that the purpose of layering is to control that the developer's code can only run at the logical layer (App Service), and the idea is to have the developer's code run at the view layer (Webview), as shown in the following diagram:

WeChat small program event system

WXS functions are used to respond to small program events, which are currently only available for built-in components and do not support custom component events. I n addition to purely logical operations, WXS functions can also access and style components by encapsulating the CompanyDescriptor instance, which is sufficient for interactive animation, style and class. An example of a WXS function is as follows:

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
}

The include event is a ComponentDescriptor instance of a component that has more event.instance on the basis of a small program event object to represent the component that triggered the event. OwnerInstance represents the ComponentDescriptor instance of the component in which the component that triggered the event is located, and if the component that triggered the event is within the page, ownerInstance represents the page instance.

ComponentDescriptor is defined as follows:

Method Parameters Describe The lowest version
selectComponent Selector object Returns the ComponentDescriptor the component.
selectAllComponents Selector object array Returns an array ComponentDescriptor of the component.
setStyle Object/string Style components to support rpx T he style priority is higher than the style defined in the component wxml. You cannot style the top-level page.
addClass/removeClass/ hasClass string Set the class of the component. T he class priority set is higher than the class defined in component wxml. You cannot set the class for the top-level page.
getDataset No 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 logical layer (App Service). FuncName represents the name of the function, and args represents the parameters of the function.
requestAnimationFrame Function It's the same as the native requestAnimationFrame Frame. Used to animate.
getState No Returns an object that uses this method when there are local variables that need to be stored for subsequent use.
triggerEvent (eventName, detail) Consistent with triggerEvent of the component.
getComputedStyle Array.<string> The parameters are consistent with computedStyle 2.11.2

WXS runs at the view layer (Webview), where the logic can do less after all, requiring a mechanism and code communication from the App Service developer, the callMethod above is the method of calling the logic layer developer's code in WXS, and WxsPropObserver is the mechanism by which the logic layer developer's code calls WXS logic.

How to use it

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

The change:prop above (with change: prefix in front of the property) is the WXS function that is triggered when the prop property is set, and the value must be enclosed with . The observer property in a component-defined properties is triggered after the setData ('propValue: newValue') call.

Note: The WXS function must be enclosed with . When the value of prop is set the WXS function is triggered, not just the value changes, so the WxsPropObserver function is called once when the page is initialized.

  • The WXS file test.wxs defines and exports functions triggered by event handler and property changes:
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. Events for native components, bindinput events for input and texttarea components are not currently supported
  2. Interactive animation is supported on 1.02.1901170 and later versions of developer tools, with the minimum version base library at 2.4.4
  3. At present, in the WXS function only supports .log log positioning problem, note that continuous duplicate logs will be filtered out.