WeChat Mini Program Framework---View Layer&Logic Layer&API&Events

Table of contents

Preface

1. Introduction to Mini Program Framework

1. Response data binding

2. Page management

3. Basic components

4. Rich API

2. View layer View

1.WXML

data binding

List rendering

Conditional rendering

template

2.WXSS

measurement unit

Style import

inline styles

Selector

Global styles and local styles

3.WXS

Example

Precautions

Page rendering

data processing

3. Logical layer App Service

1. Register the mini program

2. Registration page

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. Page life cycle

3.1. Introduction to life cycle

3.2. Life cycle execution process

Summarize

4. Page routing

4.1. Page stack

4.2.Routing method

5. Modularity

5.1.Modularization

5.2. File scope

4. API

1.Event listening API

2. Synchronization API

3. Asynchronous API

4. Asynchronous API returns Promise

5. Events

1. What is an event?

2. How to use events

3. Use WXS functions to respond to events

4. Detailed explanation of the event

4.1.Event classification

4.2. Ordinary event binding

4.3. Bind and prevent event bubbling

4.4. Mutually exclusive event binding

4.5. Event capture phase

4.6.Event object


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 WXMLand WXSS, as well as JavaScripta 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 nameto the in the view layer through the framework name, so it will be displayed when the page is opened Hello Weixin!;

  • When the button is clicked, the view layer will send changeNamethe 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 setDatathe operation of and changes from datain to , because the data and the view layer have been bound, so the view layer will automatically change to .nameWeixinMINAHello 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 @importthe statement to import the external style sheet, @importfollowed 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

  1. WXS does not depend on the base library version of the runtime and can run in all versions of small programs.

  2. WXS and JavaScript are different languages ​​and have their own syntax, which is not consistent with JavaScript.

  3. 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.

  4. WXS functions cannot be used as event callbacks for components.

  5. 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 JavaScriptan engine to provide the running environment of the developer's JavaScriptcode 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 JavaScriptfile 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 JavaScriptthe basis of , we have added some functions to facilitate the development of small programs:

  • Add Appand Pagemethods for program registration and page registration .

  • Add getAppand getCurrentPagesmethods to obtain Appthe 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 JavaScriptsome capabilities cannot be used in the web, such as window, documentetc.

1. Register the mini program

Each applet needs app.jsto call Appthe 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 getAppobtain the globally unique App instance through the method, obtain data on the App or call Appfunctions 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

jsFor 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 .

PageConstructor is suitable for simple pages. But for complex pages, Pagethe constructor may not be easy to use.

At this point, you can use Componentthe constructor to construct the page. ComponentThe 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 behaviorsand other advanced features.

Please read the Component Constructor chapter for details .

3. Page life cycle

The following diagram illustrates Pagethe 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:

  1. 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.
  2. Application level life cycle (onShow): Triggered when the applet is started or switched from the background to the foreground.
  3. Page-level life cycle (onLoad): triggered when the page loads.
  4. Page-level life cycle (onShow): triggered when the page is displayed.
  5. Page-level life cycle (onReady): triggered when the initial rendering of the page is completed.
  6. Application level life cycle (onHide): Triggered when the applet switches from the foreground to the background.
  7. Page-level life cycle (onHide): Triggered when the page switches from the foreground to the background.
  8. 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
  1. Level one will not be destroyed but will be hidden
  2. If the second level jumps to a lower level, it will be destroyed.
  3. If you jump to a higher level in the second level, it will only be hidden.
  4. 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, redirectToonly non-tabBar pages can be opened.

    • a--navigateTo--c, c-->redirectTo-->d

  • switchTabOnly tabBar pages can be opened.

  • reLaunchAny 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 onLoadbe 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:

  • exportsIt is a reference to module.exports , so changing the pointer at will in the module exportswill cause unknown errors. Therefore, it is recommended that developers use module.exportsto 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_modulesit 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 requireto 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 onAPIs 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 SyncAPIs 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 Objectparameter 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, completea Objecttype 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 Objectbe 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,否则仍按回调方式执行,无返回值。

注意事项

  1. 部分接口如 downloadFile, request, uploadFile, connectSocket, createCamera(小游戏)本身就有返回值, 它们的 promisify 需要开发者自行封装。

  2. 当没有回调参数时,异步接口返回 promise。此时若函数调用失败进入 fail 逻辑, 会报错提示 Uncaught (in promise),开发者可通过 catch 来进行捕获。

  3. 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.事件分类

事件分为冒泡事件和非冒泡事件:

  1. 冒泡事件:当一个组件上的事件被触发后,该事件会向父节点传递。

  2. 非冒泡事件:当一个组件上的事件被触发后,该事件不会向父节点传递。

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

注:除上表之外的其他组件自定义事件如无特殊声明都是非冒泡事件,如 formsubmit事件,inputinput事件,scroll-viewscroll事件,(详见各个组件)

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 会先后调用handleTap3handleTap2(因为 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 起,除 bindcatch 外,还可以使用 mut-bind 来绑定事件。一个 mut-bind 触发后,如果事件冒泡到其他节点上,其他节点上的 mut-bind 绑定函数不会被触发,但 bind 绑定函数和 catch 绑定函数依旧会被触发。

换而言之,所有 mut-bind 是“互斥”的,只会有其中一个绑定函数被触发。同时,它完全不影响 bindcatch 的绑定效果。

例如在下边这个例子中,点击 inner view 会先后调用 handleTap3handleTap2 ,点击 middle view 会调用 handleTap2handleTap1

<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-catchkeyword, which will interrupt the capture phase and cancel the bubbling phase.

In the code below, clicking the inner view will call handleTap2, handleTap4, handleTap3and 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-bindIf 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, handleTap3the received event object target and currentTarget are both inner, and handleTap2the 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 as event.currentTarget.dataset.elementType;

  • data-elementType, which will eventually be rendered 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

In the basic library version 2.7.1 or above, you can use markto identify the target node that triggers the specific event. In addition, markit can also be used to host some custom data (similar to dataset).

When the event is triggered, all on the event bubbling path markwill 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 bindViewTapand will be triggered bindButtonTap, and the events carried event.markwill contain myMarktwo anotherMarkitems.

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

markVery similar to dataset, the main difference is that markit will include all mark:attribute values ​​from the node that triggered the event to the root node; and datasetonly include data-the attribute value of one node.

Note on details:

  • If there is one with the same name mark, the parent node's markwill be overwritten by the child node.

  • When receiving events in a custom component, marknodes outside the custom component are not included mark.

  • Differently dataset, node's markwill 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 detailare the same as pageX and pageY, which represent the distance from the upper left corner of the document.

Guess you like

Origin blog.csdn.net/weixin_74268571/article/details/133845070