The view layer of the framework is written using WXML and WXSS and presented by components.
WXML (WeiXin Markup language) is used to describe the page structure;
WXS (WeiXin Script) is a scripting language for Mini Programs. Combined with WXML, it can be used to construct the page structure;
WXSS (WeiXin Style Sheet) is used to describe the page style.
Components are the building blocks of a view.
1. WXML
WXML (WeiXin Markup Language) is a markup language for framework design. It can be used to build the page structure when combined with base components and event system. The following examples show what WXML can do:
1.1 Data Binding
<view> {{message}} </view>
Page({
data: {
message: 'Hello MINA!'
}
})
1.2 List Rendering
<view wx:for="{{array}}"> {{item}} </view>
1.3 Condition Rendering
<view wx:if="{{view == 'WEBVIEW'}}"> WEBVIEW </view>
<view wx:elif="{{view == 'APP'}}"> APP </view>
<view wx:else="{{view == 'MINA'}}"> MINA </view>
Page({
data: {
view: 'MINA'
}
})
1.4 Template
<template name="staffName">
<view>
FirstName: {{firstName}}, LastName: {{lastName}}
</view>
</template>
<template is="staffName" data="{{...staffA}}"></template>
<template is="staffName" data="{{...staffB}}"></template>
<template is="staffName" data="{{...staffC}}"></template>
Page({
data: {
staffA: {firstName: 'Hulk', lastName: 'Hu'},
staffB: {firstName: 'Shang', lastName: 'You'},
staffC: {firstName: 'Gideon', lastName: 'Lin'}
}
})
2. WXSS
WXSS (WeiXin Style Sheets) is a set of style languages that describe WXML component styles,
and is used to determine how WXML components are displayed.
WXSS has most of the features of CSS to cater for the needs of front-end developers, but incorporates some new features and modifications to adapt to the development of Weixin Mini Programs.
Compared with CSS, WXSS offers the following additional features:
Dimension unit
Style import;
Dimension Unit.
Note:
For iOS 8 and below, if you use flexbox layout, you need to add display: -webkit-flex
property.
2.1 Dimension Unit
rpx (responsive pixel): Adaptable to the screen width. The specified screen width is 750 rpx. If the screen width on iPhone6 is 375 px (750 physical pixels), then 750 rpx = 375 px = 750 physical pixels, i.e. 1 rpx = 0.5 px = 1 physical pixel.
|
iPhone5 | 1rpx = 0.42px | 1px = 2.34rpx |
iPhone6 | 1rpx = 0.5px | 1px = 2rpx |
iPhone6 Plus | 1rpx = 0.552px | 1px = 1.81rpx |
Note:
Tip: Designers can use iPhone6 as a standard in Visual Design when developing Weixin Mini Programs.
Note: It is inevitable to have some glitches on small screens. Please try to avoid this during development.
2.2 Style Import
You can use the @import
statement to import external style sheet. The @import
statement should be followed by the relative path of the external style sheet and ends with ;.
@import "common.wxss";
.middle-p {
padding:15px;
}
2.3 Inline Style
You can use "style" and "class" properties for framework components to control the component style.
style: Static styles are all written to "class". "style" receives dynamic styles and parses them at runtime. It is not recommended to write static styles to "style" to avoid affecting the rendering speed.
class: Used to specify style rules. Its value is a collection of class selector names (style class names) in the style rules. The style class names do not contain . and are separated with spaces.
<view class="normal_view" />
2.4 Selectors
The following selectors are supported:
|
.class | .intro | Selects all components with class="intro" |
#id | #firstname | Selects the component with id="firstname" |
element | view | Selects all "view" components |
element, element | view, checkbox | Selects all "checkbox" components and the "view" components of all documents |
::after | view::after | Inserts content after the "view" component |
::before | view::before | Inserts content before the "view" component |
2.5 Global and Local Styles
A global style is defined in app.wxss and applies to every page, while a local one is defined in the page's wxss file and only applies to the current page (overrides the same selector in app.wxss).
3. WXS
WXS (WeiXin Script) is a script segment inlined in WXML. WXS can be used to inline a small number of processing scripts in the template to enrich the data preprocessing capability of the template. In addition, WXS can also be used to write simple WXS event response functions. Syntactically, WXS is similar to JavaScript with a few limitations. For a complete overview of the WXS syntax, see WXS - Introduction. Here are some simple examples of using WXS.
Page Rendering
<wxs module="m1">
var msg = "hello world";
module.exports.message = msg;
</wxs>
<view> {{m1.message}} </view>
Page output:
Data Processing
Page({
data: {
array: [1, 2, 3, 4, 5, 1, 2, 3, 4]
}
})
<wxs module="m1">
var getMax = function(array) {
var max = undefined;
for (var i = 0; i < array.length; ++i) {
max = max === undefined ?
array[i] :
(max >= array[i] ? max : array[i]);
}
return max;
}
module.exports.getMax = getMax;
</wxs>
<view> {{m1.getMax(array)}} </view>
Page output:
4. Event System
4.1 What Is an Event?
An event is a channel through which the view layer communicants with the logical layer;
An event can pass user's action on to the logical layer for processing;
An event can be bound to a component. When the event is triggered, the corresponding event handler is executed at the logic layer;
An event object can have additional information such as ID, dataset, touches.
4.2 How to Use an Event
Bind an event handler to the component.
For example, if the event is bindtap, the event handler can be found in the page when a user taps the component.
<view id="tapTest" data-hi="Weixin" bindtap="tapName"> Click me! </view>
Write the event handler in the Page definition with "event
" as the parameter.
Page({
tapName: function(event) {
console.log(event)
}
})
The log content is as follows:
{
"type":"tap",
"timeStamp":895,
"target": {
"id": "tapTest",
"dataset": {
"hi":"Weixin"
}
},
"currentTarget": {
"id": "tapTest",
"dataset": {
"hi":"Weixin"
}
},
"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
}]
}
4.3 Respond to Events with WXS Function
4.3.1 Background
The effect of frequent user interactions on mini programs is laggy, for example, if there are two elements A and B on a page, and the user makes a touchmove gesture on A, and asks B to follow the gesture, movable-view is a typical example. The response to a touchmove event is as follows:
The touchmove event is thrown from the rendering layer (Webview) to the logical layer (App Service);
The logical layer (App Service) handles the touchmove event and then changes the position of B through setData.
A touchmove response requires two communications between the logic layer and the rendering layer and one rendering, which is time-consuming. In addition, the setData rendering will also block the execution of other scripts, resulting in a delay in the animation process of the whole user interaction.
4.3.2 Solution
The basic idea of this solution is to reduce the number of communications and let the events respond in the rendering layer (Webview). The framework of the mini program is divided into the rendering layer (Webview) and the logic layer (App Service), the purpose of this layering is to control, the developer's code can only run in the logic layer (App Service), and this idea must allow the developer's code to run in the rendering layer (Webview).
WXS functions used to respond to mini program events, can only respond to the built-in component events, does not support custom component events.
WXS function in addition to the pure logic of the operation, but also through the encapsulated ComponentDescriptor instance to access and set the component class and style, for interactive animation, set the style and class enough.
WXS function accepts two parameters, the first is event, in the original event based on the event.instance
object, the second parameter is ownerInstance
, and event.instance
is a ComponentDescriptor
object. The specific use is as follows:
WXS functions for binding and registering event handling in a component
<wxs module="wxs" src="./test.wxs"></wxs>
<view id="tapTest" data-hi="Weixin" bindtap="{{wxs.tapName}}"> Click me! </view>
**Note: Bound WXS functions must be enclosed in {{}}**
The test.wxs file implements the tapName function.
function tapName(event, ownerInstance) {
console.log('tap Weixin', JSON.stringify(event))
}
module.exports = {
tapName: tapName
}
ownerInstance contains methods to set the style and class of the component.
An example of a WXS function is shown below:=
var wxsFunction = function(event, ownerInstance) {
var instance = ownerInstance.selectComponent('.classSelector')
instance.setStyle({
"font-size": "14px"
})
instance.getDataset()
instance.setClass(className)
return false
}
The input parameter event
is the ComponentDescriptor instance of the component that triggered the event, which is the ComponentDescriptor instance of the component that triggered the event, and the ownerInstance is the instance of the page if the component that triggered the event is inside the page.
The ownerInstance represents the ComponentDescriptor
instance of the component that triggered the event. If the component that triggered the event is inside a page, the ownerInstance represents the page instance.
The ComponentDescriptor
currently supports the following APIs.
|
selectComponent | selector objects | Returns the ComponentDescriptor instance of the component |
selectAllComponents | Array of selector objects | Returns an array of ComponentDescriptor instances of the component |
setStyle | Object/string | Set the style of the component, supports rpx, the style set has higher priority than the style defined inside the component wxml. Cannot set the style of the topmost page |
addClass/removeClass/hasClass | string | Set the class of the component, the class priority is higher than the class defined inside the component wxml. Cannot set the class of the top level page |
getDataset | - | Return the dataset of the current component/page |
callMethod | (funcName:string, args:object) | Call the function defined in the logic layer (App Service) of the current component/page. funcName is the name of the function, args is the parameter of the function |
getState | - | Returns an object, use this method when there are local variables that need to be stored for subsequent use |
triggerEvent | (eventName, detail) | Same as the triggerEvent of the component |
4.3.3 Usage
WXML defines the event:
<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 the change: prefix in front of the property) triggers the WXS function when the prop property is set, and the value must be enclosed in {{}}
. Similarly the observer property inside properties defined by Component is triggered after a setData({propValue: newValue})
call.
Note:
WXS functions must be enclosed in {{}}
. The WXS function is triggered when the value of the prop is set, not just when the value is changed, so the WxsPropObserver function is called once when the page is initialised.
The WXS file test.wxs
defines and exports event handlers and functions triggered by 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)
}
}
4.4Events
4.4.1 Event Types
Events are divided into bubbling events and non-bubbling ones.
Bubbling event: When an event is triggered on a component, this event is propagated to the component's parent node;
Non-bubbling event: When an event is triggered on a component, this event is not propagated to the component's parent node.
WXML bubbling events:
|
touchstart | Finger touch starts |
touchmove | Finger moves after touch |
touchcancel | Finger touch is interrupted by call reminder, pop-up window, etc. |
touchend | Finger touch ends |
tap | The finger leaves the screen after touch |
longpress | The finger leaves the screen after it taps and holds on the screen for more than 350 ms. If an event callback function is specified and this event is triggered, the tap event is not triggered. |
longtap | The finger leaves the screen after it taps and holds on the screen for more than 350 ms (it is recommended to use longpress event instead). |
transitionend | Triggered when a WXSS transition or wx.createAnimation animation ends |
animationstart | Triggered when a WXSS animation starts |
animationiteration | Triggered after an iteration of a WXSS animation ends |
animationend | Triggered when a WXSS animation completes |
touchforcechange | Triggered when the screen is tapped again on an iPhone supporting 3D Touch. |
Note:
Unless otherwise specified, the custom events of components other than those listed above are non-bubbling events, such as the submit event of [form]((form), input event of [input]((input), and scroll event of [scroll-view](scroll-view). For more information, see Component Overview. 4.4.2 Event Binding and Bubbling
Event bindings are written similarly to component properties, e.g.:
<view bindtap="handleTap">
Click here!
</view>
If the user clicks on this view, the page's handleTap is called.
The event binding function can be a data binding, e.g.:
<view bindtap="{{ handlerName }}">
Click here!
</view>
In this case, the page's this.data.handlerName must be a string specifying the name of the event handler; if it's an empty string, the binding is disabled (you can use this feature to temporarily disable some events).
In most components and custom components, bind can be immediately followed by a colon, and the meaning remains the same, e.g. bind:tap
4.4.3 Binding and stopping event bubbling
In addition to bind, events can also be bound with catch. Unlike bind, catch prevents events from bubbling up.
For example, in the following example, clicking on the inner view calls handleTap3 and handleTap2 successively (because the tap event bubbles up to the middle view, which prevents the tap event from bubbling up to the parent node), and clicking on the middle view triggers handleTap2, which triggers handleTap2, which triggers handleTap2, which triggers handleTap2, which triggers handleTap2, which triggers handleTap2. Click outer view will trigger 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>
4.4.4 Mutually exclusive event binding
As of Base Library version 1.5.44, you can use mut-bind to bind events in addition to bind and catch. When a mut-bind is triggered, if the event bubbles to another node, the mut-bind bindings on the other node will not be triggered, but the bind and catch bindings will still be triggered.
In other words, all mut-binds are "mutually exclusive" and only one of them will be triggered. At the same time, it doesn't affect the binding effect of bind and catch at all.
For example, in the example below, clicking inner view will call handleTap3 and handleTap2, and clicking middle view will call 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>
4.4.5 Event Capturing
touch-related events support capturing. In event capturing, which precedes bubbling, events arrive at nodes in an order reverse of that in which they do during bubbling. To listen to events during capturing, use capture-bind
or capture-catch
as the keyword. The latter interrupts the capturing and cancels bubbling.
In the code below, tap "inner view" to call handleTap2
, handleTap4
, handleTap3
, and handleTap1
in turn.
<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 the first capture-bind in the above code is changed to capture-catch, only handleTap2 is 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>
4.4.6 Event Objects
Unless otherwise specified, when the component triggers an event, the handler bound to the event at logic layer receives an event object.
BaseEvent object properties:
|
| String | Event Type |
| Integer | Timestamp when the event is generated |
| Object | A collection of property valuesfor the component triggering the event |
| Object | A collection of property valuesfor the current component |
| Object | Event flag data |
CustomEvent object properties (inherit from BaseEvent):
|
detail | Object | Additional information |
TouchEvent object properties (inherit from BaseEvent):
|
touches | Array | Touch event. An array of information of touch points staying in the screen. |
changedTouches | Array | Touch event. An array of information of touch points involving changes in the screen |
Special events: The touch events in canvas are non-bubbling events and thus have no currentTarget.
4.4.7 type
Represents the type of an event.
4.4.8 timeStamp
Number of milliseconds from the moment when the page is opened until the event is triggered.
4.4.9 target
The source component triggering the event.
|
id | String | ID of the event source component |
| Object | A collection of custom properties starting with data- on the event source component |
4.4.10 currentTarget
The current component bound to the event.
|
id | String | Current component ID |
| Object | A collection of custom properties starting with data- on the current component |
Note:
You can refer to the above example for "target" and "currentTarget". When you tap "inner view", the event objects "target" and "currentTarget" received by handleTap3 are both "inner", but the "target" and "currentTarget" received by handleTap2 are "inner" and "middle", respectively.
4.4.11 dataset
You can add some custom data to the component node so as to obtain the custom node data from the event for logical processing.
In WXML, these custom data begins with data- and multiple words are joined with hyphen -. In the code, a hyphenation is converted to camel case, and the uppercase characters are automatically converted to lowercase ones. For example:
data-element-type is converted to event.currentTarget.dataset.elementType;
data-elementType is converted to 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
}
})
4.4.12 touches
"touches" is an array, in which each element is a Touch object ("touches" in the canvas touch event is a CanvasTouch array). Touch points staying in the screen.
Touch objects
|
identifier | Number | Touch point identifier |
pageX, pageY | Number | Distance from the upper left corner of the document. The top left corner is the origin, the horizontal line is X-axis, and the vertical line is Y-axis. |
clientX, clientY | Number | Distance from the upper left corner of the page display area (the area on the screen without navigation pane). The horizontal line is X-axis and the vertical line is Y-axis. |
CanvasTouch objects
|
identifier | Number | Touch point identifier |
x, y | Number | Distance from the upper left corner of Canvas. Canvas's upper left corner is the origin, the horizontal line is X-axis, and the vertical line is Y-axis. |
4.4.13 changedTouches
Indicates the touch points involving changes (in the same format as "touches"), including touchstart (appearance of touch point), touchmove (movement of touch point), and touchend/touchcancel (disappearance of touch point).
4.4.14 detail
The data carried by the custom event. For example, the submission event of a form component carries user's input, and the error event of media carries the error message. For more information, see the event definitions in Component Overview. Similar to pageX and page Y, the x and y in detail of the tap event represent the distance from the upper left corner of the document.
5. Basic Components
The framework provides developers with a set of basic components that can be combined to achieve quick development. For more information, see Component Overview. What is component?
A component is the basic building block of a view layer;
A component includes a start tag
, end tag
, property (modifies the component), and content (between the two tags).
<tagname property="value">
Content goes here ...
</tagname>
Note:
All components and properties are in lowercase and joined with a hyphen -
Property Types
|
Boolean | Boolean value | If a component has this property, the property value is always considered true regardless of what the actual value is. The property value is false only when the component has no this property.
If the property value is a variable, the variable is converted to a Boolean value. |
Number | Number | 1, 2.5 |
String | String | "string" |
Array | Array | [ 1, "string" ] |
Object | Object | { key: value } |
EventHandler | Event handler | "handlerName" is the event handler name defined in Page |
Any | Any property | - |
Common Properties
All components have the following properties:
|
id | String | A unique identifier of a component | Remains unique across the entire page. |
class | String | Component style class | The style class defined in the WXSS |
style | String | Component inline style | This is an inline style that can be dynamically set |
hidden | Boolean | Whether to display the component | All components are displayed by default |
data-* | Any | Custom property | When an event is triggered on the component, it is sent to the event handler |
bind* / catch* | EventHandler | Component event | |
Special Properties
Almost all components have their own custom properties. You can modify the features or style of the component. See the definition of each Component Overview. 6. Getting Node Information on Interface
6.1 WXML Node Information
This API is mostly used to query the current position and scroll position of a node in the interface.
Sample code:
const query = wx.createSelectorQuery()
query.select('#the-id').boundingClientRect(function(res){
res.top
})
query.selectViewport().scrollOffset(function(res){
res.scrollTop
})
query.exec()
In the above example, #the-id is a node selector, which is slightly different from the CSS selector. For more information, see SelectorQuery.select. In custom components or pages that contain custom components, it is recommended to use this.createSelectorQuery, instead of wx.createSelectorQuery, to ensure nodes are selected within the correct area. 6.2 WXML Node Layout Intersection
The APIs for node layout intersection is used to listen to the layout intersection between two or more component nodes. This set of APIs are often used to determine whether certain nodes are visible to users and the percentage of the visible area. The set of APIs involve the following concepts:
Reference node: The reference node for listening, whose layout area is taken as the reference area. If there are multiple reference nodes, the intersection of their layout areas is taken as the reference area. The page display area can also be used as a reference area;
Target node: The target to be listened to. Only one target node is allowed by default (you can listen to multiple nodes at the same time using the selectAll option);
Intersection area: The intersection area between the layout area of the target node and the reference area;
Intersection percentage: The percentage of the intersection area in the reference area
Threshold: If the intersection percentage reaches the threshold, the callback function of the listener is triggered. Multiple thresholds can be set;
In the following sample code, a callback function is triggered each time the target node (specified using the selector .target-class) enters or exits the page display area.
Sample code:
Page({
onLoad: function(){
wx.createIntersectionObserver().relativeToViewport().observe('.target-class', (res) => {
res.id
res.dataset
res.intersectionRatio
res.intersectionRect
res.intersectionRect.left
res.intersectionRect.top
res.intersectionRect.width
res.intersectionRect.height
})
}
})
The following sample code can be in the target node (specified with the selector .target-class) and the reference node (specified with the selector .relative-class) in the page display area of the intersection or separation, and the degree of intersection or separation to the extent of the layout of the target node of the area of the 20% and 50%, trigger the callback function.
Sample code:
Page({
onLoad: function(){
wx.createIntersectionObserver(this, {
thresholds: [0.2, 0.5]
}).relativeTo('.relative-class').relativeToViewport().observe('.target-class', (res) => {
res.intersectionRatio
res.intersectionRect
res.intersectionRect.left
res.intersectionRect.top
res.intersectionRect.width
res.intersectionRect.height
})
}
})
Note:
The intersection area with the page display area does not accurately represent the area visible to users, because the area involved in the calculation is the "layout area", which may be cropped or hidden by, for example, a node whose ancestor node has the overflow style "hidden", or obscured by, for example, a node with fixed position during drawing.
In custom components or pages that contain custom components, it is recommended to use this.createIntersectionObserver, instead of wx.createIntersectionObserver, to ensure nodes are selected within the correct area. 7. Respond to Changes in Display Area
7.1 Display Area Size
The display area refers to the area in Mini Program interface where you can arrange elements freely. By default, the size of the display area remains unchanged after the page initialization. But you can change the default size by either of the following two ways.
Enable Screen Rotation on a Phone
To allow the Mini Program pages to support screen rotation, set "pageOrientation": "auto" in the window
segment of app.json
, or configure "pageOrientation": "auto"
in the page json file.
The following example shows how to enable screen rotation in a single page json file.
Code example:
{
"pageOrientation": "auto"
}
If the above declaration is added to the page, the page rotates and the display area is resized as the screen rotates.pageOrientation
can be set to landscape, which locks the screen orientation to "Landscape".
Enable Screen Rotation on an iPad
To allow the Mini Program to support screen rotation, add "resizable": true to app.json.
Code example:
If the above declaration is added to the Mini Program, the Mini Program page rotates and the display area is resized as the screen rotates.
Note:
You cannot enable or disable screen rotation for a single page.
7.2 Media Query
Sometimes, the page layout varies with the size of the display area. You can use "media query" to solve most of the problems.
Code example:
.my-class {
width: 40px;
}
@media (min-width: 480px) {
.my-class {
width: 200px;
}
}
7.3 Screen Rotation Event
Sometimes, subtle layout changes cannot be controlled by using "media query" alone. In this case, js can be used.
The onResize of the page can be used to listen to the page resizing event. For custom components, you can use the "resize lifecycle" function to listen to the event. The callback function returns the size of the display area.
Code example:
Page({
onResize(res) {
res.size.windowWidth
res.size.windowHeight
}
})
Component({
pageLifetimes: {
resize(res) {
res.size.windowWidth
res.size.windowHeight
}
}
})
In addition, you can also use wx.onWindowResize to listen to the event (not recommended).
8. Animation
8.1 Common User Interface Animations
In Mini Programs, you can use CSS transitions and CSS animations to create simple UI animations.
During the animation creation, you can use bindtransitionend
, bindanimationstart
, bindanimationiteration
, and bindanimationend
to listen to animation events.
|
transitionend | A CSS transition ends or a step of wx.createAnimation ends |
animationstart | CSS animation starts |
animationiteration | A step of CSS animation ends |
animationend | A CSS animation ends |
Note:
These events are not bubbling events and need to be bound to the node that is being animated to take effect.
It is also possible to use the wx.createAnimation interface to dynamically create simple animation effects (the keyframe animation interface described below is recommended in the new version of the mini program base library instead).
8.2 Advanced Animations
The above animations may not be applicable to complicated scenarios.
You can dynamically adjust the "style" property of a node by responding to events with WXS. Changing the value of "style" continuously can produce animation effects. And this method can be used to dynamically generate animations based on users' touch events. Animation effects can also be achieved by using setData to change the user interface continuously. This can change the interface arbitrarily, but usually produces a large delay or stutter, and even causes the Mini Program to freeze. In this case, you can improve performance by changing the setData of the page to the setData in Custom Components. The following example shows how to generate a stopwatch animation using setData.
Was this page helpful?