Summary of the pitfalls you may not have encountered in WeChat applet development

Summary of the pitfalls you may not have encountered in WeChat applet development

getApp()

The getApp() function is used to obtain the app instance. Generally, there is no problem, but it will bring you unexpected bugs in several special scenarios.
Use in the onLaunch callback function in app.js

// app.js
App({
 onLaunch() {
  console.info(getApp(), '!!');
 }
});

You will find that undefined is output at this time, which is understandable. After all, it is still in the initialization stage and the app has not yet been born. If the code is just that simple, you can easily find this problem. Once you call a method in it, and this method accidentally obtains the app instance to obtain the variable, an accident will occur.

So~ If there is no synchronization requirement, you can call the function in onLaunch and wrap it with setTimout to avoid pitfalls:

// app.js
App({
 onLaunch() {
  setTimeout(() => {
   // ... call other functions });
 }
});

Assign getApp() to a variable

We create a js file:

// a.js
const app = getApp();

export function checkVersion() {
 console.log('checked!');
 console.info('app', app, '!!');
}

The above files will generally not cause any problems, but once you import them into app.js, surprises will arise.

// app.js
import { checkVersion } from 'a';

App({
 onLaunch() {
  console.log('I\'m Fine!');
 },
 onShow() {
  checkVersion();
 }
});

At this time, you will find that the app variable is undefined. This kind of error may be difficult to detect, especially for a packaged general library, which works fine at ordinary times, but suddenly breaks down when it is used in app.js.

So~ To avoid this problem, try to reduce the sharing of public app instances, and instead use getApp() directly in the method to get the instance object. If you want to use global variables, it would be better to store the variables in a separate js file, for example:

// globalStore.js

export default {
 userInfo: null,
 isIos: false,
 isLaunched: false,
};
// app.js
import store from 'globalStore';

App({
 onLaunch() {
  store.isLaunched = true;
 },
 onShow() {
  const { isLaunched } = getApp().store,
  console.log(isLaunched);
 },
 store,
});

This way, you can obtain global variables by importing modules, and you can also obtain global variables through getApp().store.

But in principle I still recommend reading and writing global variables by importing modules. After all, getApp() returns undefined in some cases.

Define variables at the top of your page entry file

It is common to define variables in the page entry file, but you must note that the page entry file will only be executed once, not independently for each page instance, such as the following code:

// pages/page/index.js
import { getDetailInfo } from 'api';
let ajaxLock = false;

Page({
 onLoad() {
  this.getRemoteData();
 },
 async getRemoteData() {
  if (ajaxLock) {
   return;
  }
  ajaxLock = true;
  try {
   await getDetailInfo();
  } catch(err) {
   // ... handle errors } finally {
   ajaxLock = false;
  }
 },
});

The page logic is relatively simple. It requests remote data as soon as the page is entered. Visually, there is no problem. However, once you open multiple pages at the same time, you will find that only the first page requests data, and the subsequent pages do not request it. This is because these pages all share the ajaxLock variable. Therefore, when declaring variables at the top of the page, you must pay attention to the usage scenarios.

Directly assign global variables to data in the page entry file

Directly on the code:

// pages/page/index.js
Page({
 data: {
  isIos: getApp().store.isIos,
 },
});

// app.js
App({
 onLaunch() {
  this.getSysInfo();
 },
 getSysInfo() {
  return new Promise((resolve, reject) => {
   wx.getSystemInfoAsync({
    success: resolve,
    fail: reject,
   });
  }).then((res) => {
   const { store } = getApp();
   store.isIos = res.platform.toLowerCase() === 'ios';
  });
 },
 store: {
  isIos: false,
 },
});

The main logic of the above code is to know whether the current device is iOS. The code seems to be very stable when running on the simulator, but once it is on the real machine, it is sometimes good and sometimes bad, because the isIos variable does not get the status synchronously. Once the value is assigned after the page entry function is executed, the status display will be incorrect.
Therefore, for some states that are not assigned synchronously, never assign values ​​to data directly during initialization. It is best to assign the state in the onLoad callback function.

What you don't know about wx.createSelectorQuery() and wx.createIntersectionObserver();

These two functions are also commonly used. wx.createSelectorQuery is mainly used to query an element, and wx.createIntersectionObserver is used to process whether the element is in the visible area. The problems of these two functions are cute at first glance. I only discovered them when I was implementing a special requirement. It was really hindsight, and I felt it was powerful without knowing it. It was terrifying when I thought about it carefully...

Let's reproduce the problem. The page entry function is written like this:

// pages/page/index.js
let index = 0

Page({
 data: {
  tag: 0
 },
 onLoad() {
  if (index++ < 2) {
   wx.navigateTo({
    url: '/pages/page/index'
   });
  }
  this.setData({
   tag: index
  },() => {
   setTimeout(() => {
    const { tag } = this.data;
    const query = wx.createSelectorQuery();
    // const query = this.createSelectorQuery();
    query.select(`.c-${ tag }`).boundingClientRect();
    query.exec((res) => {
     console.log(tag, res);
    });
   }, 2000);
  });
 }
});

<!-- Template file-->
<view class="c-{{tag}}">demo</view>

I simulated the situation of opening multiple pages at the same time. In the developer tools, you will find that the results of the first two pages are null! ! ! At that time, I felt like the world was falling apart. So I suspect that after all wx.createSelectorQuery is a global function, so it queries the wxml under the currently active window. How to solve it? I flipped through the official documentation, looked for the small print with a magnifying glass, and found the method this.createSelectorQuery. I gave it a try, and the problem was suddenly solved. Of course wx.createIntersectionObserver has the same problem, so I won’t demonstrate it.

So~ for health reasons, I strongly recommend using this.createSelectorQuery and this.createIntersectionObserver directly.

The above are the pitfalls I have encountered in developing WeChat applets in recent years. I hope you don’t fall into them again~~

Summarize

This concludes this article about the pitfalls in WeChat Mini Program development that you may not have encountered. For more information about the pitfalls in WeChat Mini Program development, please search for previous articles on 123WORDPRESS.COM or continue to browse the related articles below. I hope you will support 123WORDPRESS.COM in the future!

You may also be interested in:
  • Summary of the pitfalls encountered when using taro to develop WeChat applets
  • Echarts’s pitfalls in Taro WeChat applet development
  • WeChat applet development chapter: pitfall record

<<:  Undo log in MySQL

>>:  How to collect Nginx logs using Filebeat

Recommend

How to uninstall Linux's native openjdk and install sun jdk

See: https://www.jb51.net/article/112612.htm Chec...

Three examples of blur background effects using CSS3

Let’s not start with the introduction and get str...

Docker uses busybox to create a base image

The first line of a Docker image starts with an i...

Example code for implementing dynamic skinning with vue+element

Sometimes the theme of a project cannot satisfy e...

A brief discussion on the use of Web Storage API

Table of contents 1. Browser local storage techno...

How to use time as a judgment condition in MySQL

Background: During the development process, we of...

HTML+Sass implements HambergurMenu (hamburger menu)

A few days ago, I watched a video of a foreign gu...

CSS to achieve floating customer service effect

<div class="sideBar"> <div>...

How to use the Linux basename command

01. Command Overview basename - strip directories...

Windows Server 2019 IIS10.0+PHP(FastCGI)+MySQL Environment Construction Tutorial

Preparation 1. Environmental Description: Operati...

MySQL 8.0.15 installation and configuration method graphic tutorial

This article records the installation and configu...