Table of contents
1. Introduction to Mini Program Framework
Global styles and local styles
3.WXS
2.1. Use the Page constructor to register the page
2.2. Use behaviors in the page
2.3. Use the Component constructor to construct the page
3.1. Introduction to life cycle
3.2. Life cycle execution process
4. Asynchronous API returns Promise
3. Use WXS functions to respond to events
4. Detailed explanation of the event
4.3. Bind and prevent event bubbling
4.4. Mutually exclusive event binding
Preface
When starting to use WeChat developer tools for small program development, we need to master the basic syntax of the view layer (WXML) and logic layer (JS). This blog will introduce how to write code for the view layer and logic layer in WeChat developer tools.
1. Introduction to Mini Program Framework
The goal of the mini program development framework is to allow developers to develop services with native APP experience in WeChat in the simplest and most efficient way possible.
The entire mini program framework system is divided into two parts: the logic layer (App Service) and the view layer (View). The applet provides its own view layer description language
WXML
andWXSS
, as well asJavaScript
a logic layer framework based on , and provides data transmission and event systems between the view layer and the logic layer, allowing developers to focus on data and logic.
1. Response data binding
At the core of the framework is a reactive data binding system that makes it very simple to keep data in sync with views. When modifying data, you only need to modify the data in the logical layer, and the view layer will update accordingly.
Let’s look at this simple example:
Preview the effect in developer tools
<!-- This is our View -->
<view> Hello {
{name}}! </view>
<button bindtap="changeName"> Click me! </button>
// This is our App Service.
// This is our data.
var helloData = {
name: 'Weixin'
}
// Register a Page.
Page({
data: helloData,
changeName: function(e) {
// sent data change to view
this.setData({
name: 'MINA'
})
}
})
The developer binds the in the logic layer data
name
to the in the view layer through the frameworkname
, so it will be displayed when the page is openedHello Weixin!
;When the button is clicked, the view layer will send
changeName
the event to the logic layer, and the logic layer will find and execute the corresponding event processing function;After the callback function is triggered, the logic layer performs
setData
the operation of and changes fromdata
in to , because the data and the view layer have been bound, so the view layer will automatically change to .name
Weixin
MINA
Hello MINA!
2. Page management
The framework manages the page routing of the entire mini program , can achieve seamless switching between pages, and gives the page a complete life cycle. All the developer needs to do is to register the page's data, methods, and life cycle functions into the framework, and all other complex operations are handled by the framework.
- wx.navigateTo(Object object) : Keep the current page and jump to a page in the application. Use wx.navigateBack to return to the original page.
- wx.redirectTo(Object object) : Close the current page and jump to a page within the application. Return is not allowed.
- wx.reLaunch(Object object) : Close all pages and open a page within the application.
- wx.switchTab(Object object) : Jump to the tabBar page and close all other non-tabBar pages.
3. Basic components
The framework provides a set of basic components, which come with WeChat-style styles and special logic. Developers can create powerful WeChat mini programs by combining basic components .
- view : View container, similar to div in HTML.
- image : Picture component, used to display network or local pictures.
- text : text component, used to display text content.
- button : Button component, used to trigger events.
- input : Input box component, used for users to input text.
- picker : A selector component used to select a value from a predefined data list.
- swiper : Carousel component, used to display multiple pictures or slides.
- scroll-view : A scrollable view area component that supports horizontal and vertical scrolling.
The above are only some of the basic components provided by the mini program. Developers can choose appropriate components to build pages according to their needs.
4. Rich API
The framework provides a wealth of WeChat native APIs, which can easily activate the capabilities provided by WeChat, such as obtaining user information, local storage, payment functions, etc.
Commonly used APIs:
- wx.request(Object object) : Initiate a network request.
- wx.getStorageSync(String key) : Synchronously obtain the content corresponding to the specified key from the local cache.
- wx.setStorageSync(String key, Any data) : Store data in the specified key in the local cache.
- wx.getSystemInfoSync() : Get system information, including device, network, screen and other information.
- wx.getLocation(Object object) : Get the current geographical location information.
- wx.showLoading(Object object) : Display the loading prompt box.
- wx.hideLoading() : Hide the loading prompt box.
The above are only some of the APIs provided by the mini program. Developers can choose the appropriate API according to their needs to implement the corresponding functions.
2. View layer View
The view layer of the framework is written in WXML and WXSS and displayed by components.
Reflect the data of the logical layer into the view, and send the events of the view layer to the logical layer.
- WXML (WeiXin Markup language) is used to describe the structure of the page.
- WXS (WeiXin Script) is a set of script languages for small programs. When combined
WXML
, the structure of the page can be constructed.- WXSS (WeiXin Style Sheet) is used to describe the style of the page.
- Component is the basic unit of view.
1.WXML
WXML (WeiXin Markup Language) is a set of tag languages designed by the framework. Combined with basic components and event systems , it can build the structure of the page.
The following are some features of WXML :
- Tags and attributes : WXML uses tags and attributes to build the component structure of the page. By defining different tags and properties, we can create various UI components.
- Data binding : WXML supports data binding function, which can display dynamic content in the view. By binding data to a view using double curly braces ({ {}}), the view automatically updates when the data changes.
- Conditional judgment and looping : WXML provides conditional judgment and looping syntax, which can determine whether to display a component based on conditions, and can generate multiple identical or similar components in a loop.
- Event binding : The view layer supports event binding, which can associate user operations (such as clicks, slides, etc.) with methods in the logic layer to achieve corresponding interactive feedback.
Commonly used WXML syntax:
- { {}} : Double curly braces indicate data binding, which can display data in the view and update automatically.
- wx:if : Conditional judgment syntax, which determines whether to display a component based on conditions. It can be used with wx:else and wx:elif.
- wx:for : Loop syntax, loop to generate multiple identical or similar components based on data.
- bind : event binding syntax, which can associate user operations (such as clicks, slides, etc.) with methods in the logic layer to achieve corresponding interactive feedback.
For a complete understanding of WXML syntax, refer to the WXML Syntax Reference .
Use the following simple examples to see what WXML is capable of:
data binding
wxml
<view> {
{message}} </view>
page.js
Page({
data: {
message: 'Hello MINA!'
}
})
List rendering
WXML
<view wx:for="{
{array}}"> {
{item}} </view>
page.js
Page({
data: {
array: [1, 2, 3, 4, 5]
}
})
Conditional rendering
WXML
<view wx:if="{
{view == 'WEBVIEW'}}"> WEBVIEW </view>
<view wx:elif="{
{view == 'APP'}}"> APP </view>
<view wx:else="{
{view == 'MINA'}}"> MINA </view>
page.js
Page({
data: {
view: 'MINA'
}
})
template
WXML
<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.js
Page({
data: {
staffA: {firstName: 'Hulk', lastName: 'Hu'},
staffB: {firstName: 'Shang', lastName: 'You'},
staffC: {firstName: 'Gideon', lastName: 'Lin'}
}
})
The specific capabilities and usage methods can be found in the following chapters:
Data binding , list rendering , conditional rendering , templates , references
2.WXSS
WXSS (WeiXin Style Sheets) is a style language used to describe WXML component styles.
WXSS is used to determine how WXML components should be displayed.
In order to adapt to the majority of front-end developers, WXSS has most of the features of CSS. At the same time, in order to be more suitable for developing WeChat applets, WXSS has expanded and modified CSS.
Compared with CSS, the features of WXSS extensions are:
-
measurement unit
-
Style import
measurement unit
-
rpx (responsive pixel): can be adapted according to the screen width. The specified screen width is 750rpx. For example, on iPhone6, the screen width is 375px and there are 750 physical pixels in total, then 750rpx = 375px = 750 physical pixels, 1rpx = 0.5px = 1 physical pixel.
equipment | rpx to px (screen width/750) | px conversion rpx (750/screen width) |
---|---|---|
iPhone5 | 1rpx = 0.42px | 1px = 2.34rpx |
iPhone6 | 1rpx = 0.5px | 1px = 2rpx |
iPhone6 Plus | 1rpx = 0.552px | 1px = 1.81rpx |
Suggestion: When developing WeChat applets, designers can use iPhone6 as the standard for visual drafts.
Note: There will inevitably be some glitches on smaller screens, please try to avoid this when developing.
Style import
Use @import
the statement to import the external style sheet, @import
followed by the relative path of the external style sheet that needs to be imported, and ;
end the statement with.
Sample code:
/** common.wxss **/
.small-p {
padding:5px;
}
/** app.wxss **/
@import "common.wxss";
.middle-p {
padding:15px;
}
inline styles
Framework components support using style and class attributes to control the style of the component.
-
style: Static styles are uniformly written into classes. style receives dynamic styles and will parse them at runtime. Please try to avoid writing static styles into style to avoid affecting the rendering speed.
<view style="color:{
{color}};" />
-
class: used to specify style rules. Its attribute value is a collection of class selector names (style class names) in the style rules. The style class names do not need to be included
.
, and the style class names are separated by spaces.
<view class="normal_view" />
Selector
Currently supported selectors are:
Selector | Sample | Sample description |
---|---|---|
.class | .intro |
Select all components with class="intro" |
#id | #firstname |
Select the component with id="firstname" |
element | view |
Select all view components |
element, element | view, checkbox |
Select all document view components and all checkbox components |
::after | view::after |
Insert content after the view component |
::before | view::before |
Insert content before the view component |
Global styles and local styles
The styles defined in app.wxss are global styles and apply to every page. The styles defined in the wxss file of the page are local styles, which only apply to the corresponding page and will override the same selector in app.wxss.
3.WXS
WXS (WeiXin Script) is a set of script languages for small programs. When combined WXML
, the structure of the page can be constructed.
Example
-
Create a new wxs file
var toDecimal2 = function (x) {
var f = parseFloat(x);
if (isNaN(f)) {
return '0.00'
}
var f = Math.round(x * 100) / 100;
var s = f.toString();
var rs = s.indexOf('.');
if (rs < 0) {
rs = s.length;
s += '.';
}
while (s.length <= rs + 2) {
s += '0';
}
return s;
}
//module.exports = toDecimal2
module.exports = {
toDecimal2:toDecimal2
}
-
Use in wxml
<!--pages/c/c.wxml-->
<wxs src="../../wxs/PageUtils.wxs" module="PageUtils"></wxs>
<wxs module="m1">
var msg = "hello world";
module.exports.message = msg;
</wxs>
<view>
<text>pages/c/c.wxml,</text>
<text>{
{m1.message}}</text>
<view>
<text>{
{PageUtils.toDecimal2(123.453)}}</text>
</view>
<view>
<button type="primary" bindtap="jump">跳转到D页面</button>
</view>
</view>
Precautions
-
WXS does not depend on the base library version of the runtime and can run in all versions of small programs.
-
WXS and JavaScript are different languages and have their own syntax, which is not consistent with JavaScript.
-
The running environment of WXS is isolated from other JavaScript codes. Functions defined in other JavaScript files cannot be called in WXS, nor can APIs provided by mini programs be called.
-
WXS functions cannot be used as event callbacks for components.
-
Due to differences in operating environments, WXS in mini programs on iOS devices will be 2 to 20 times faster than JavaScript code. There is no difference in operating efficiency between the two on Android devices.
The following are some simple examples using WXS. For a complete understanding of WXS syntax, please refer to the WXS Syntax Reference .
Page rendering
<!--wxml-->
<wxs module="m1">
var msg = "hello world";
module.exports.message = msg;
</wxs>
<view> {
{m1.message}} </view>
Page output:
hello world
data processing
// page.js
Page({
data: {
array: [1, 2, 3, 4, 5, 1, 2, 3, 4]
}
})
<!--wxml-->
<!-- 下面的 getMax 函数,接受一个数组,且返回数组中最大的元素的值 -->
<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>
<!-- 调用 wxs 里面的 getMax 函数,参数为 page.js 里面的 array -->
<view> {
{m1.getMax(array)}} </view>
Page output:
5
3. Logical layer App Service
The logic layer of the mini program development framework uses JavaScript
an engine to provide the running environment of the developer's JavaScript
code and the unique functions of the WeChat mini program for the mini program.
The logic layer processes the data and sends it to the view layer, and at the same time accepts event feedback from the view layer.
All the code written by the developer will eventually be packaged into a JavaScript
file and run when the applet is started until the applet is destroyed. This behavior is similar to ServiceWorker , so the logic layer is also called App Service.
On
JavaScript
the basis of , we have added some functions to facilitate the development of small programs:
Add
App
andPage
methods for program registration and page registration .Add
getApp
andgetCurrentPages
methods to obtainApp
the instance and current page stack respectively.Provides rich APIs , such as WeChat user data, scanning, payment and other WeChat-specific capabilities.
Provides modular capabilities, and each page has an independent scope .
Note: The logic layer of the mini program framework does not run in the browser, so JavaScript
some capabilities cannot be used in the web, such as window
, document
etc.
1. Register the mini program
Each applet needs app.js
to call App
the method in to register the applet instance, bind the life cycle callback function, error monitoring and page non-existence monitoring functions, etc.
For detailed parameter meanings and usage, please refer to the App reference documentation .
// app.js
App({
onLaunch (options) {
// Do something initial when launch.
},
onShow (options) {
// Do something when show.
},
onHide () {
// Do something when hide.
},
onError (msg) {
console.log(msg)
},
globalData: 'I am global data'
})
The entire mini program has only one App instance, which is shared by all pages. Developers can getApp
obtain the globally unique App instance through the method, obtain data on the App or call App
functions registered by developers on.
// xxx.js
const appInstance = getApp()
console.log(appInstance.globalData) // I am global data
Definition of foreground and background: When the user clicks on the upper left corner to close, or presses the home button of the device to leave WeChat, the mini program is not destroyed directly, but enters the background; when the user enters WeChat again or opens the mini program again, it will enter the foreground from the background .
Only when the mini program enters the background for a certain period of time, or if the system resource usage is too high, will it be truly destroyed.
Notice:
1. Do not call getApp() in the function defined in App(). Use this to get the app instance.
2. Do not call getCurrentPage() during onLaunch, when the page has not been generated yet.
3. After obtaining the instance through getApp(), do not call the life cycle function privately
2. Registration page
js
For each page in the mini program, it needs to be registered in the file corresponding to the page , specifying the page's initial data, life cycle callbacks, event processing functions, etc.
2.1. Use the Page constructor to register the page
Simple pages can Page()
be constructed using .
Code example:
//index.js
Page({
data: {
text: "This is page data."
},
onLoad: function(options) {
// 页面创建时执行
},
onShow: function() {
// 页面出现在前台时执行
},
onReady: function() {
// 页面首次渲染完毕时执行
},
onHide: function() {
// 页面从前台变为后台时执行
},
onUnload: function() {
// 页面销毁时执行
},
onPullDownRefresh: function() {
// 触发下拉刷新时执行
},
onReachBottom: function() {
// 页面触底时执行
},
onShareAppMessage: function () {
// 页面被用户分享时执行
},
onPageScroll: function() {
// 页面滚动时执行
},
onResize: function() {
// 页面尺寸变化时执行
},
onTabItemTap(item) {
// tab 点击时执行
console.log(item.index)
console.log(item.pagePath)
console.log(item.text)
},
// 事件响应函数
viewTap: function() {
this.setData({
text: 'Set some data for updating view.'
}, function() {
// this is setData callback
})
},
// 自由数据
customData: {
hi: 'MINA'
}
})
For detailed parameter meanings and usage, please refer to the Page reference document .
2.2. Use behaviors in the page
Basic library 2.9.2 starts to support it, and lower versions need to be compatible .
Pages can reference behaviors. Behaviors can be used to allow multiple pages to have the same data fields and methods.
// my-behavior.js
module.exports = Behavior({
data: {
sharedText: 'This is a piece of data shared between pages.'
},
methods: {
sharedMethod: function() {
this.data.sharedText === 'This is a piece of data shared between pages.'
}
}
})
// page-a.js
var myBehavior = require('./my-behavior.js')
Page({
behaviors: [myBehavior],
onLoad: function() {
this.data.sharedText === 'This is a piece of data shared between pages.'
}
})
See behaviors for specific usage .
2.3. Use the Component constructor to construct the page
Basic library 1.6.3 starts to support it, and lower versions need to be compatible .
Page
Constructor is suitable for simple pages. But for complex pages, Page
the constructor may not be easy to use.
At this point, you can use Component
the constructor to construct the page. Component
The main difference with constructors is that methods need to be placed methods: { }
inside.
Code example:
Component({
data: {
text: "This is page data."
},
methods: {
onLoad: function(options) {
// 页面创建时执行
},
onPullDownRefresh: function() {
// 下拉刷新时执行
},
// 事件响应函数
viewTap: function() {
// ...
}
}
})
This way of creation is very similar to custom components and can be used like custom components behaviors
and other advanced features.
Please read the Component Constructor chapter for details .
3. Page life cycle
The following diagram illustrates Page
the life cycle of a page instance.
When writing a WeChat applet, you have to know its life cycle. If you don't know the applet, various bugs will appear that cannot be solved.
The applet is composed of two major threads: the thread responsible for the interface (view thread) and the service thread (appservice thread). Each performs its own duties and cooperates with each other.
3.1. Introduction to life cycle
The life cycle in mini programs can be divided into two types:
- Application-level life cycle : refers to the life cycle of the entire applet, from startup to destruction.
- Page-level life cycle : refers to the life cycle of a single page, from loading to unloading.
Application-level life cycle of mini program:
- onLaunch(options) : Triggered when the applet is initialized, options are the startup parameters of the applet.
- onShow(options) : Triggered when the mini program starts or switches from the background to the foreground. options is the entry scene value of the mini program.
- onHide() : Triggered when the applet switches from the foreground to the background.
- onError(error) : Triggered when an error occurs in the applet, and error is the error object.
Page-level life cycle of mini program:
- onLoad(options) : Triggered when the page is loaded, options are the parameters of the page.
- onShow() : triggered when the page is displayed.
- onReady() : Triggered when the initial rendering of the page is completed.
- onHide() : Triggered when the page switches from the foreground to the background.
- onUnload() : Triggered when the page is unloaded.
3.2. Life cycle execution process
Mini program life cycle execution process:
- Application level life cycle (onLaunch): Mini program initialization will only be triggered once when the mini program is started. If the mini program is opened again after being killed, it will not be retriggered.
- Application level life cycle (onShow): Triggered when the applet is started or switched from the background to the foreground.
- Page-level life cycle (onLoad): triggered when the page loads.
- Page-level life cycle (onShow): triggered when the page is displayed.
- Page-level life cycle (onReady): triggered when the initial rendering of the page is completed.
- Application level life cycle (onHide): Triggered when the applet switches from the foreground to the background.
- Page-level life cycle (onHide): Triggered when the page switches from the foreground to the background.
- Page-level life cycle (onUnload): triggered when the page is unloaded.
The life cycle corresponding to Tab switching (take pages A and B as Tabbar pages, C is the page opened from page A, and page D is the page opened from page C):
The current page | Post-routing page | Lifecycle of triggers (in order) |
---|---|---|
A | A | Nothing happend |
A | B | A.onHide(), B.onLoad(), B.onShow() |
A | B (open again) | A.onHide(), B.onShow() |
C | A | C.onUnload(), A.onShow() |
C | B | C.onUnload(), B.onLoad(), B.onShow() |
D | B | D.onUnload(), C.onUnload(), B.onLoad(), B.onShow() |
D (enter from forwarding) | A | D.onUnload(), A.onLoad(), A.onShow() |
D (enter from forwarding) | B | D.onUnload(), B.onLoad(), B.onShow() |
Summarize
- Level one will not be destroyed but will be hidden
- If the second level jumps to a lower level, it will be destroyed.
- If you jump to a higher level in the second level, it will only be hidden.
- All pages in the middle of the generation skip will be destroyed.
4. Page routing
The routing of all pages in the mini program is managed by the framework.
4.1. Page stack
The framework maintains all current pages in the form of a stack. When a routing switch occurs, the page stack behaves as follows:
routing method | Page stack performance |
---|---|
initialization | New page pushed into stack |
Open new page | New page pushed into stack |
page redirect | The current page is popped out of the stack and the new page is pushed into the stack. |
Page return | The page continues to pop off the stack until the target returns to the page |
Tab switch | All pages are popped out of the stack, leaving only the new Tab page. |
Reload | All pages are popped out of the stack, leaving only new pages. |
Developers can use getCurrentPages()
the function to obtain the current page stack.
4.2.Routing method
The routing triggering method and page life cycle functions are as follows:
routing method | Trigger time | pre-routing page | Post-routing page |
---|---|---|---|
initialization | The first page opened by the mini program | onLoad, onShow | |
Open new page | Call API wx.navigateTo using component `` | onHide | onLoad, onShow |
page redirect | Call API wx.redirectTo using component `` | onUnload | onLoad, onShow |
Page return | Call the API wx.navigateBack using the component `` The user presses the return button in the upper left corner | onUnload | onShow |
Tab switch | Call API wx.switchTab to use the component `` User Switch Tab | Please refer to the table below for various situations | |
Restart | Call API wx.reLaunch using component `` | onUnload | onLoad, onShow |
Precautions
navigateTo
,redirectTo
only non-tabBar pages can be opened.
a--navigateTo--c, c-->redirectTo-->d
switchTab
Only tabBar pages can be opened.
reLaunch
Any page can be opened.The tabBar at the bottom of the page is determined by the page, that is, as long as the page is defined as a tabBar, there will be a tabBar at the bottom.
The parameters taken by the calling page route can
onLoad
be obtained from the target page.
5. Modularity
5.1.Modularization
Some common code can be extracted into a separate js file as a module. Modules can only expose interfaces to the outside world through module.exports or .exports
Notice:
-
exports
It is a reference to module.exports , so changing the pointer at will in the moduleexports
will cause unknown errors. Therefore, it is recommended that developers usemodule.exports
to expose module interfaces, unless you already clearly know the relationship between the two. -
The mini program currently does not support direct introduction
node_modules
. When developers need to use it,node_modules
it is recommended to copy the relevant code to the directory of the mini program, or use the npm function supported by the mini program.
// common.js
function sayHello(name) {
console.log(`Hello ${name} !`)
}
function sayGoodbye(name) {
console.log(`Goodbye ${name} !`)
}
module.exports.sayHello = sayHello
exports.sayGoodbye = sayGoodbye
In the files that need to use these modules, use require
to introduce the public code; you can also use import to import
var common = require('common.js')
Page({
helloMINA: function() {
common.sayHello('MINA')
},
goodbyeMINA: function() {
common.sayGoodbye('MINA')
}
})
5.2. File scope
Variables and functions declared in a JavaScript file are only valid in that file; variables and functions with the same name can be declared in different files without affecting each other.
The global application instance can be obtained through the global function getApp
. If global data is needed, it can App()
be set in , such as:
// app.js
App({
globalData: 1
})
// a.js
// The localValue can only be used in file a.js.
var localValue = 'a'
// Get the app instance.
var app = getApp()
// Get the global data and change it.
app.globalData++
// b.js
// You can redefine localValue in file b.js, without interference with the localValue in a.js.
var localValue = 'b'
// If a.js it run before b.js, now the globalData shoule be 2.
console.log(getApp().globalData)
4. API
The mini program development framework provides a wealth of WeChat native APIs, which can easily activate the capabilities provided by WeChat, such as obtaining user information, local storage, payment functions, etc. Please refer to the API documentation for detailed introduction .
Usually, there are the following types of mini program APIs:
1.Event listening API
We agree that on
APIs starting with are used to monitor whether an event is triggered, such as: wx.onSocketOpen , wx.onCompassChange , etc.
This type of API accepts a callback function as a parameter. When an event is triggered, the callback function will be called and relevant data will be passed in as a parameter.
code example
wx.onCompassChange(function (res) {
console.log(res.direction)
})
2. Synchronization API
We agree that Sync
APIs ending with are synchronous APIs, such as wx.setStorageSync , wx.getSystemInfoSync , etc. In addition, there are some other synchronization APIs, such as wx.createWorker , wx.getBackgroundAudioManager , etc. For details, please refer to the instructions in the API documentation.
The execution result of the synchronous API can be obtained directly through the function return value. If an execution error occurs, an exception will be thrown.
code example
try {
wx.setStorageSync('key', 'value')
} catch (e) {
console.error(e)
}
3. Asynchronous API
Most APIs are asynchronous APIs, such as wx.request , wx.login , etc. This type of API interface usually accepts a Object
parameter of type, which supports specifying the following fields as needed to receive the interface call result:
Object parameter description
parameter name | type | Required | illustrate |
---|---|---|---|
success | function | no | Callback function for successful interface call |
fail | function | no | Callback function for interface call failure |
complete | function | no | The callback function at the end of the interface call (executed whether the call is successful or failed) |
other | Any | - | Other parameters defined by the interface |
callback function parameters
success
, fail
, complete
a Object
type parameter will be passed in when the function is called, including the following fields:
Attributes | type | illustrate |
---|---|---|
errMsg | string | Error message, returned if the call is successful${apiName}:ok |
errCode | number | Error code, only supported by some APIs. Please refer to the corresponding API documentation for the specific meaning. When successful 0 . |
other | Any | Other data returned by the interface |
The execution result of the asynchronous API needs to Object
be obtained through the corresponding callback function passed in the type parameter. Some asynchronous APIs will also have return values, which can be used to implement richer functions, such as wx.request , wx.connectSocket , etc.
code example
wx.login({
success(res) {
console.log(res.code)
}
})
4. Asynchronous API returns Promise
基础库 2.10.2 版本起,异步 API 支持 callback & promise 两种调用方式。当接口参数 Object 对象中不包含 success/fail/complete 时将默认返回 promise,否则仍按回调方式执行,无返回值。
注意事项
部分接口如
downloadFile
,request
,uploadFile
,connectSocket
,createCamera
(小游戏)本身就有返回值, 它们的 promisify 需要开发者自行封装。当没有回调参数时,异步接口返回 promise。此时若函数调用失败进入 fail 逻辑, 会报错提示
Uncaught (in promise)
,开发者可通过 catch 来进行捕获。wx.onUnhandledRejection 可以监听未处理的 Promise 拒绝事件。
代码示例
// callback 形式调用
wx.chooseImage({
success(res) {
console.log('res:', res)
}
})
// promise 形式调用
wx.chooseImage().then(res => console.log('res: ', res))
五、事件
1.什么是事件
-
事件是视图层到逻辑层的通讯方式。
-
事件可以将用户的行为反馈到逻辑层进行处理。
-
事件可以绑定在组件上,当达到触发事件,就会执行逻辑层中对应的事件处理函数。
-
事件对象可以携带额外信息,如 id, dataset, touches。
2.事件的使用方式
-
在组件中绑定一个事件处理函数。
如bindtap
,当用户点击该组件的时候会在该页面对应的 Page 中找到相应的事件处理函数。
<view id="tapTest" data-hi="Weixin" bindtap="tapName"> Click me! </view>
-
在相应的 Page 定义中写上相应的事件处理函数,参数是event。
Page({
tapName: function(event) {
console.log(event)
}
})
-
可以看到 log 出来的信息大致如下:
{
"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
}]
}
3.使用 WXS 函数响应事件
基础库 2.4.4 开始支持,低版本需做兼容处理。
从基础库版本2.4.4
开始,支持使用 WXS 函数绑定事件,WXS函数接受2个参数,第一个是event,在原有的 event 的基础上加了event.instance
对象,第二个参数是ownerInstance
,和event.instance
一样是一个ComponentDescriptor
对象。具体使用如下:
-
在组件中绑定和注册事件处理的 WXS 函数。
<wxs module="wxs" src="./test.wxs"></wxs>
<view id="tapTest" data-hi="Weixin" bindtap="{
{wxs.tapName}}"> Click me! </view>
注:绑定的 WXS 函数必须用{ {}}括起来
-
test.wxs文件实现 tapName 函数
function tapName(event, ownerInstance) {
console.log('tap Weixin', JSON.stringify(event))
}
module.exports = {
tapName: tapName
}
ownerInstance
包含了一些方法,可以设置组件的样式和class,具体包含的方法以及为什么要用 WXS 函数响应事件,请点击查看详情。
4.事件详解
4.1.事件分类
事件分为冒泡事件和非冒泡事件:
冒泡事件:当一个组件上的事件被触发后,该事件会向父节点传递。
非冒泡事件:当一个组件上的事件被触发后,该事件不会向父节点传递。
WXML的冒泡事件列表:
类型 | 触发条件 | 最低版本 |
---|---|---|
touchstart | 手指触摸动作开始 | |
touchmove | 手指触摸后移动 | |
touchcancel | 手指触摸动作被打断,如来电提醒,弹窗 | |
touchend | 手指触摸动作结束 | |
tap | 手指触摸后马上离开 | |
longpress | 手指触摸后,超过350ms再离开,如果指定了事件回调函数并触发了这个事件,tap事件将不被触发 | 1.5.0 |
longtap | 手指触摸后,超过350ms再离开(推荐使用 longpress 事件代替) | |
transitionend | 会在 WXSS transition 或 wx.createAnimation 动画结束后触发 | |
animationstart | 会在一个 WXSS animation 动画开始时触发 | |
animationiteration | 会在一个 WXSS animation 一次迭代结束时触发 | |
animationend | 会在一个 WXSS animation 动画完成时触发 | |
touchforcechange | 在支持 3D Touch 的 iPhone 设备,重按时会触发 | 1.9.90 |
注:除上表之外的其他组件自定义事件如无特殊声明都是非冒泡事件,如 form 的submit
事件,input 的input
事件,scroll-view 的scroll
事件,(详见各个组件)
4.2.普通事件绑定
事件绑定的写法类似于组件的属性,如:
<view bindtap="handleTap">
Click here!
</view>
如果用户点击这个 view ,则页面的 handleTap
会被调用。
事件绑定函数可以是一个数据绑定,如:
<view bindtap="{
{ handlerName }}">
Click here!
</view>
此时,页面的 this.data.handlerName
必须是一个字符串,指定事件处理函数名;如果它是个空字符串,则这个绑定会失效(可以利用这个特性来暂时禁用一些事件)。
自基础库版本 1.5.0 起,在大多数组件和自定义组件中, bind
后可以紧跟一个冒号,其含义不变,如 bind:tap
。基础库版本 2.8.1 起,在所有组件中开始提供这个支持。
4.3.绑定并阻止事件冒泡
除 bind
外,也可以用 catch
来绑定事件。与 bind
不同, catch
会阻止事件向上冒泡。
例如在下边这个例子中,点击 inner view 会先后调用handleTap3
和handleTap2
(因为 tap 事件会冒泡到 middle view,而 middle view 阻止了 tap 事件冒泡,不再向父节点传递),点击 middle view 会触发handleTap2
,点击 outer view 会触发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.互斥事件绑定
自基础库版本 2.8.2 起,除 bind
和 catch
外,还可以使用 mut-bind
来绑定事件。一个 mut-bind
触发后,如果事件冒泡到其他节点上,其他节点上的 mut-bind
绑定函数不会被触发,但 bind
绑定函数和 catch
绑定函数依旧会被触发。
换而言之,所有 mut-bind
是“互斥”的,只会有其中一个绑定函数被触发。同时,它完全不影响 bind
和 catch
的绑定效果。
例如在下边这个例子中,点击 inner view 会先后调用 handleTap3
和 handleTap2
,点击 middle view 会调用 handleTap2
和 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.5.事件的捕获阶段
As of base library version 1.5.0 , touch class events support the capture phase. The capture phase precedes the bubbling phase, and in the capture phase, the order in which events arrive at nodes is exactly the opposite of the bubbling phase. When you need to listen for events during the capture phase, you can use the capture-bind
, capture-catch
keyword, which will interrupt the capture phase and cancel the bubbling phase.
In the code below, clicking the inner view will call handleTap2
, handleTap4
, handleTap3
and 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>
capture-bind
If you change the first one in the code above to capture-catch
, it will only fire handleTap2
.
<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.6.Event object
Unless otherwise specified, when a component triggers an event, the handler function bound to the event by the logic layer will receive an event object.
BaseEvent base event object property list:
Attributes | type | illustrate | Base library version |
---|---|---|---|
type | String | event type | |
timeStamp | Integer | The timestamp when the event was generated | |
target | Object | A collection of some property values of the component that triggered the event | |
currentTarget | Object | A collection of some attribute values of the current component | |
mark | Object | event tag data | 2.7.1 |
CustomEvent custom event object property list (inherits BaseEvent):
Attributes | type | illustrate |
---|---|---|
detail | Object | additional information |
TouchEvent touch event object property list (inherits BaseEvent):
Attributes | type | illustrate |
---|---|---|
touches | Array | Touch event, array of touch point information currently staying on the screen |
changedTouches | Array | Touch event, array of currently changed touch point information |
Special events: Touch events in canvas cannot bubble, so there is no currentTarget.
type
Represents the type of event.
timeStamp
The number of milliseconds that elapsed between the page being opened and the event being triggered.
target
The source component that triggered the event.
Attributes | type | illustrate |
---|---|---|
id | String | The id of the event source component |
dataset | Object | data- A collection of custom properties starting with |
currentTarget
The current component the event is bound to.
Attributes | type | illustrate |
---|---|---|
id | String | The id of the current component |
dataset | Object | data- A collection of custom properties starting with |
Note: Target and currentTarget can refer to the above example. When the inner view is clicked,
handleTap3
the received event object target and currentTarget are both inner, andhandleTap2
the received event object target is inner and currentTarget is middle.
dataset
Some custom data can be appended to component nodes. In this way, these customized node data can be obtained in the event and used for logical processing of the event.
In WXML, this custom data begins with data-
, and multiple words are connected by hyphens -
. In this writing method, hyphens will be converted to camel case, and uppercase characters will automatically be converted to lowercase characters. like:
data-element-type
, which will eventually be rendered asevent.currentTarget.dataset.elementType
;
data-elementType
, which will eventually be rendered asevent.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
In the basic library version 2.7.1 or above, you can use mark
to identify the target node that triggers the specific event. In addition, mark
it can also be used to host some custom data (similar to dataset
).
When the event is triggered, all on the event bubbling path mark
will be merged and returned to the event callback function. (This happens even if the event is not a bubbling event mark
.)
Code example:
Preview the effect in developer tools
<view mark:myMark="last" bindtap="bindViewTap">
<button mark:anotherMark="leaf" bindtap="bindButtonTap">按钮</button>
</view>
In the above WXML, if the button is clicked, two events bindViewTap
and will be triggered bindButtonTap
, and the events carried event.mark
will contain myMark
two anotherMark
items.
Page({
bindViewTap: function(e) {
e.mark.myMark === "last" // true
e.mark.anotherMark === "leaf" // true
}
})
mark
Very similar to dataset
, the main difference is that mark
it will include all mark:
attribute values from the node that triggered the event to the root node; and dataset
only include data-
the attribute value of one node.
Note on details:
If there is one with the same name
mark
, the parent node'smark
will be overwritten by the child node.When receiving events in a custom component,
mark
nodes outside the custom component are not includedmark
.Differently
dataset
, node'smark
will not do hyphen and case conversion.
touches
touches is an array, and each element is a Touch object (the touches carried in the canvas touch event are CanvasTouch arrays). Indicates the touch point currently on the screen.
Touch object
Attributes | type | illustrate |
---|---|---|
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 horizontal axis is the X axis and the vertical axis is the Y axis. |
clientX, clientY | Number | Distance from the upper left corner of the displayable area of the page (excluding the navigation bar on the screen). The horizontal axis is the X axis and the vertical axis is the Y axis. |
CanvasTouch object
Attributes | type | illustrate | Special Instructions |
---|---|---|---|
identifier | Number | The identifier of the touch point | |
x, y | Number | The distance from the upper left corner of the Canvas. The upper left corner of the Canvas is the origin. The horizontal axis is the X axis and the vertical axis is the Y axis. |
changedTouches
The data format of changedTouches is the same as touches. Indicates a changed touch point, such as changing from nothing to something (touchstart), changing position (touchmove), and changing from something to nothing (touchend, touchcancel).
detail
The data carried by custom events, such as the submission event of the form component will carry the user's input, and the error event of the media will carry error information. For details, see the definition of each event in the component definition.
The x and y in the click event detail
are the same as pageX and pageY, which represent the distance from the upper left corner of the document.