Summary of strengthening the basics of WeChat mini programs

This article brings you some related questions about WeChat applets . It mainly introduces some basic content, including custom components, style isolation, data, methods and attributes, etc. Let’s take a look at them together. Everyone is helpful.

1. Custom components

1.1. Create components

  • In the root directory of the project, right-click and create components -> test folder

  • On the newly created components -> test folder, right-click and click New Component

  • Type the name of the component and press Enter. Four files corresponding to the component will be automatically generated, with the suffixes being .js, .json, .wxml and .wxss.

1.2. Reference components

  • Local reference: the component can only be used within the currently referenced page

  • Global reference: the component can be used in every applet page

1.3. Local reference components

The way of referencing components in the .json configuration file of the page is called local reference. The sample code is as follows:

 

# 在页面的 .json 文件中,引入组件
{
  "usingComponents": {
    "my-test": "/components/test/test"
  }
}
# 在页面的 .wxml 文件中,使用组件
<my-test></my-test>

1.4. Global reference components

The way to reference components in the app.json global configuration file is called global reference. The sample code is as follows:

# 在 app.json 文件中,引入组件
{
  "usingComponents": {
    "my-test": "/components/test/test"
  }
}

 

1.5. Global references VS local references

Choose the appropriate reference method based on the frequency and scope of use of the component:

  • If a component is frequently used in multiple pages, it is recommended to reference it globally.

  • A certain component is only used in a specific page. It is recommended to make a local reference.

1.6, the difference between components and pages

On the surface, components and pages are composed of four files: .js, .json, .wxml, and .wxss. However, there are significant differences between .js and .json files for components and pages:

  • The "component": true attribute needs to be declared in the component's .json file

  • The Component() function is called in the component's .js file

  • The component's event handling function needs to be defined in the methods node

2. Style isolation

2.1. Component style isolation

By default, the style of a custom component only takes effect on the current component and will not affect the UI structure outside the component.

Prevent external styles from affecting the internal styles of components

Prevent component styles from destroying external styles

2.2. Notes on component style isolation

Global styles in app.wxss are not valid for components

Only class selectors have style isolation effects, id selectors, attribute selectors, and label selectors are not affected by style isolation

It is recommended to use class selectors in components and pages that reference components. Do not use id, attribute, and label selectors.

2.3. Modify the style isolation options of the component

By default, the style isolation feature of custom components can prevent the internal and external styles of the component from interfering with each other. But sometimes, we want to be able to control the style inside the component from the outside. At this time, you can modify the component's style isolation options through stylelsolation. The usage is as follows:

# 在组件的 .js 文件中新增如下配置
Component({
  options: {
    stylelsolation: 'isolated'
  }
})
# 或在组件的 .json 文件中新增如下配置
{
  "stylelsolation": "isolated"
}

 

2.4. Optional values ​​of stylesolation

| Optional values ​​| Default value | Description |

| isolated | Yes | Indicates that style isolation is enabled | Indicates that style isolation is enabled. Within and outside the custom component, the styles specified using class will not affect each other |

| apply-shared | No| Indicates that the page wxss style will affect the custom component, but the style specified in the custom component wxss will not affect the page |

| shared | No | means that the wxss style of the page will affect the custom component, and the style specified in the custom component wxss will also affect the page and other custom components that are set to apply-shared or shared |

3. Data, methods and properties

3.1, data data

In the applet component, it is used for component template rendering and private data, which needs to be defined in the data node. The example is as follows:

Component({
  <!-- 组件的初始数据 -->
  data: {
    count: 0
  }
})

 

3.2. methods data

In the applet component, event handling functions and custom methods need to be defined in the methods node. The sample code is as follows:

Component({
   <!-- 组件的方法列表 -->
  methods: {
    <!-- 事件处理函数 -->
    addCount() {
      this.setData({count: this.data.count + 1});
      <!-- 通过 this 直接调用自定义方法 -->
      this._showCount()
    },
    <!-- 自定义方法建议以 _ 开头 -->
    _showCount() {
      wx.showToast({
        title: 'count值为:' + this.data.count,
        icon: 'none'
      })
    }
  }
})

 

3.3. properties

In the mini program component, properties are the external properties of the component and are used to receive data passed to the component from the outside world. The sample code is as follows:

Component({
  <!-- 属性定义 -->
  properties: {
    <!-- 完整定义属性的方式 -->
    max: {
      type: Number,
      value: 10
    },
    <!-- 简化定义属性的方式 -->
    max: Number
  }
})

 

3.4. The difference between data and properties

In the components of the mini program, the properties and data are used in the same way. They are both readable and writable, but:

  • data is more inclined to store private data of components

  • properties are more inclined to store data passed to the component from the outside world

Component({
  methods: {
    showInfo() {
      <!-- 结果为 true,证明 data 数据和 properties 属性本质上是一样的,都是可读可写的 -->
      console.log(this.data === this.properties)
    }
  }
})

 

3.5. Use setData to modify the value of properties

Since there is no essential difference between data and properties, the value of the properties property can also be used for page rendering, or setData can be used to reassign the properties in properties. The sample code is as follows:

# 在组建的 .wxml 文件中使用 properties 属性的值
<view>max属性的值为:{
   
   {max}}</view>
Component({
  properties: { max: Number },
  methods: {
    addCount() {
      this.setData({ max: this.properties.max + 1 })
    }
  }
})

 

4. Data listener

4.1. What is a data listener?

Data listeners are used to listen and respond to changes in any properties and data fields to perform specific operations. Its function is similar to the watch listener in vue. In the applet component, the basic syntax format of the data listener is as follows:

Component({
  observers: {
    '字段A, 字段B': function(字段A的心智, 字段B的新值) {
    }
  }
})

 4.2. Basic usage of data listener

Component({
  data: { n1: 0, n2: 0, sum: 0 },
  methods: {
    addN1() { sthis.setData({ n1: this.data.n1 + 1 })},
    addN2() { sthis.setData({ n2: this.data.n2 + 1 })}
  },
  observers: {
    'n1, n2': function(n1, n2) {
      this.setData({sum: n1 + n2})
    }
  }
})

 4.3. Monitor changes in object properties

# 数据监听器支持监听对象中单个或多个属性的变化,示例代码如下:
Component({
  observers: {
    '对象.属性A, 对象.属性B': function(属性A的新值, 属性B的心智){}
  }
})
# 监听对象中所有属性的变化
Component({
  observers: {
    'obj.**': function(obj){}
  }
})

 

5. Pure data fields

5.1. What is a pure data field?

Pure data fields refer to those data fields that are not used for interface rendering.

Application scenarios: For example, in some cases, fields in certain data will neither be displayed on the interface nor passed to other components, but will only be used within the current component. Data fields with this characteristic are suitable for setting as storage data fields.

Benefit: Pure data fields help improve page update performance

5.2. Rules of use

In the options node of the Component constructor, specify pureDataPattern as a regular expression. Fields whose field names match this regular expression will become pure data fields. The sample code is as follows:

Component({
  options: {
    <!-- 指定所有 _ 开头的数据字段为纯数据字段 -->
    pureDataPattern: /^_/
  },
  data: {
    a: true, // 普通数据字段
    _b: true // 纯数据字段
  }
})

 

6. Component life cycle

6.1. All life cycle functions of components

 

 

6.2. Main life cycle functions of components

Among mini program components, there are three most important life cycle functions, namely created, attached, and detached. Their respective characteristics are as follows:

  • When the component instance is just created, the created lifecycle function will be triggered

setData cannot be called at this time

Usually in this life cycle function, it should only be used to add some custom attribute fields to this of the component.

  • After the component is fully initialized and the page node tree is entered, the attached life cycle function will be triggered.

At this point, this.data has been initialized.

This life cycle is very useful, most initialization work can be performed at this time

  • After the component leaves the page node tree, the detached life cycle function will be triggered.

When exiting a page, the detached life cycle function of each custom component in the page will be triggered.

This is a good time to do some cleaning work

6.3, lifetimes node

In the applet component, the life cycle function can be directly defined in the first-level parameter of the Component constructor, and can be declared in the lifetimes field (this is the recommended way, and its priority is the highest). The sample code is as follows:

Component({
  <!-- 推荐用法 -->
  lifetimes: {
    attached() {}, // 在组件实例进入页面节点树时执行
    detached() {}, // 在组件实例被从页面节点树移除时执行
  },
  <!-- 以下是旧的定义方式 -->
  attached() {}, // 在组件实例进入页面节点树时执行
  detached() {}, // 在组件实例被从页面节点树移除时执行
})

 

6.4. What is the life cycle of the page where the component is located?

Sometimes, the behavior of a custom component depends on changes in the page state. In this case, you need to use the life cycle of the page where the component is located.

 

6.5, pageLifetimes node 

# 组件所在页面的生命周期函数,需要定义在 pageLifetimes 节点中
Component({
  pageLifetimes: {
    show: function() {}, // 页面被展示
    hide: function() {}, // 页面被隐藏
    resize: function(size) {} // 页面尺寸变化
  }
})

 

7. Slot

7.1. What is a slot?

In the wxml structure of a custom component, a slot node (slot) can be provided to host the wxml structure provided by the component user.

7.2. Single slot

In the mini program, by default only one slot is allowed to be used in each custom component. This limit on the number is called a single slot.

<!-- 组件的封装者 -->
<view class="wrapper">
  <view>这里是组件的内部节点</view>
  <!-- 对于不准确的内容,可以使用 slot 进行展位 -->
  <slot></slot>
</view>
<!-- 组件的使用者 -->
<component>
  <view>这里是插入到组件slot中的内容</view>
</component>

 

7.3. Enable multiple slots

In the custom component of the mini program, if you need to use multiple slots, you can enable them in the .js file of the component in the following way. The sample code is as follows:

Component({
  options: {
    multipleSlots: true // 在组件定义时,启用多个 slot 支持
  }
})

 

7.4. Define multiple slots

You can use multiple slot tags in the component's .wxml to distinguish different slots with different names. The sample code is as follows:

<!-- 组件模板 -->
<view class="wrapper">
  <!-- name 为 before 的第一个 slot 插槽 -->
  <slot name="before"></slot>
  <view>这是一段固定的文本内容</view>
  <!-- name 为 after 的第二个 slot 插槽 -->
  <slot name="after"></slot>
</view>

 

7.5. Use multiple slots

When using a custom component with multiple slots, you need to use the slot attribute to insert nodes into different slots. The sample code is as follows:

<!-- 引用组件的页面模板 -->
<component>
  <!-- 这部分内容将被放置在组件 <slot name="before"></slot> 的位置上 -->
  <view slot="before">这里是插入到组件 slot name="before"中的内容</view>
  <!-- 这部分内容将被放置在组件 <slot name="after"></slot> 的位置上 -->
  <view slot="after">这里是插入到组件 slot name="after"中的内容</view>
</component>

 

8. Communication between parent and child components

8.1. Three ways of communication between parent and child components

Property binding

Used by parent components to set data to specified properties of child components. Only JSON-compatible data can be set.

event binding

Used for child components to pass data to parent components. Any data can be passed

Get component instance

The parent component can also obtain the child component instance object through this.selectComponent()

In this way, you can directly access any data and methods of the subcomponent

8.2. Attribute binding

Property binding is used to transfer values ​​​​from parent to child, and can only pass ordinary types of data, and cannot pass methods to child components. The sample code of the parent component is as follows:

<!-- 父组件的 data 节点 -->
data: {
  count: 0
}
<!-- 父组件的 wxml 结构 -->
<my-child count="{
   
   {count}}"></my-child>

 

<!-- 子组件的 properties 节点 -->
properties: {
  count: Number
}
<!-- 子组件的 wxml -->
<view>子组件种,count值为:{
   
   {count}}</view>

8.3. Event binding

Event binding is used to transfer values ​​from the child to the parent, and any type of data can be passed. The usage steps are as follows:

In the js of the parent component, define a function, which will be passed to the child component in the form of a custom event

<!-- 在父组件定义 syncCount 方法,将来传递给子组件,供子组件进行调用 -->
syncCount() {
  console.log('syncCount')
}

 In the wxml of the parent component, pass the function reference defined in step 1 to the child component in the form of a custom event

<!-- 使用bind:自定义事件名称(推荐:结构清晰) -->
<my-test count="{
   
   {count}}" bind:sync="syncCount"></my-test>
<!-- 使用bind后面直接协商自定义事件名称-->
<my-test count="{
   
   {count}}" bindsync="syncCount"></my-test>

 In the js of the child component, send data to the parent component by calling this.triggerEvent('custom event name', {parameter object})

<!-- 子组件的 wxml 结构 -->
<text>子组件中,count:{
   
   {count}}</text>
<button type="primary" bindtap="addCount">+1</button>
# 子组件的 js 代码
methods: {
  addCount() {
    this.setData({
      count: this.properties.count + 1
    })
    this.triggerEvent('sync', { value: this.properties.count })
  }
}

 In the js of the parent component, the data passed by the child component is obtained through e.detail

syncCount(e) {
  this.setData({
    count: e.detail.value
  })
}

 

8.4. Obtain component instance

You can call this.selectComponent('id or class selector') in the parent component to obtain the instance object of the child component, thereby directly accessing any data and methods of the child component.

<my-component count="{
   
   {count}}" bind:sync="syncCount" class="test" id="test"></my-component>
<button bindtap="getChild">获取子组件实例</button>
<!-- 按钮的 tap 事件处理函数 -->
getChild() {
  <!-- 可以传递 id选择器,也可以传递 class 选择器 -->
  const child = this.selectComponent('.test')
  <!-- 调用子组件的 setData 方法 -->
  child.setData({ count: child.properties.count + 1 })
  <!-- 调用子组件的 addCount 方法 -->
  child.addCount()
}

 

9、behaviors

9.1. What are behaviors?

Behaviors is a feature used to implement code sharing between components in small programs, similar to mixins in Vue.js

9.2. How behaviors work

Each behavior can contain a set of properties, data, lifecycle functions and methods. When a component references it, its attributes, properties, and methods are merged into the component.

Each component can reference multiple behaviors, and behaviors can also reference other behaviors.

9.3. Create behavior

Call the Behavior(Object object) method to create a shared behavior instance object for use by all components

# 调用 Behavior() 方法,创建实例对象
# 并使用 module.exports 将 behavior 实例对象共享出去
module.exports = Behavior({
  # 属性节点
  properties: {},
  # 私有数据节点
  data: {},
  # 事件处理函数和自定义方法节点
  methods: {}
})

 

9.4. Import and use behavior

In the component, use the require() method to import the required behavior. After mounting, you can access the data or methods in the behavior. The sample code is as follows:

# 使用 require() 导入需要自定义 behavior 模块
const myBehavior = require('my-behavior')
Component({
  <!-- 将导入的 behavior 实例对象,挂载到 behaviors 数组节点中即可生效 -->
  behaviors: [myBehavior]
})

 9.5. All available nodes in behavior

 

10. Use npm package

10.1. Small programs support and restrictions on npm

Currently, mini programs already support the use of npm to install third-party packages, thereby improving the development efficiency of mini programs. However, there are three limitations to using npm packages in small programs:

  • Packages that depend on Node.js built-in libraries are not supported

  • Packages that rely on browser built-in objects are not supported

  • Packages that depend on C++ plugins are not supported

10.2, API Promising

  • Disadvantages of callback-based asynchronous APIs

By default, the official asynchronous APIs provided by Mini Programs are implemented based on callback functions. For example, APIs for network requests need to be called as follows:

 

wx.request({
  method: '',
  url: '',
  data: {},
  success: () => {}
})

 

Disadvantages: It is easy to cause the problem of callback hell, and the readability and maintainability of the code are poor.

  • What is API Promise?

API Promise refers to upgrading the officially provided callback function-based asynchronous API to a Promise-based asynchronous API through additional configuration, thereby improving the readability and maintainability of the code and avoiding the problem of callback hell.

  • Implement API Promise

In mini programs, implementing API Promise mainly relies on the third-party npm package minprogram-api-promise. Its installation and use steps are as follows:

npm install --save minprogram-api-promise
# 在小程序入口文件中(app.js),只需要调用一次 promisifyAll() 方法
import { promisifyAll } from 'minprogram-api-promise'
const wxp = wx.p = {}
promisifyAll(wx, wxp)

 Call the asynchronous API after Promise

# 页面的 .wxml 结构
<button bindtap="getInfo">vant按钮</button>
# 在页面的 .js 文件中,定义对应的 tap 事件处理函数
async getInfo() {
  const { data: res } = await wx.p.request({
    method: 'GET',
    url: '',
    data: {}
  })
}

 

11. Global data sharing

11.1. What is global data sharing?

Global data sharing (also known as: state management) is to solve the problem of data sharing between components

Commonly used data sharing solutions in development include: Vuex, Redux, MobX, etc.

11.2. Global data sharing scheme in mini programs

In mini programs, mobx-miniprogram can be used together with mobx-miniprogram-bindings to achieve global data sharing. in:

  • mobx-miniprogram is used to create Store instance objects

  • mobx-miniprogram-bindings is used to bind shared data or methods in Store to components or pages for use

Install MobX related packages

# 在项目运行如下的命令,安装MobX相关的包
npm install --save mobx-miniprogram mobx-miniprogram-bindings

 

Note: After the MobX related packages are installed, remember to delete the miniprogram_npm directory and rebuild npm

Create a Store instance of MobX

import { observable, action } from 'mobx-miniprogram'
export const store = observable({
  // 数据字段
  numA: 1,
  numB: 2,
  //计算属性
  get sum() {
    return this.numA + this.numB
  },
  // actions 方法,用来修改 store 中的数据
  updateNumA: action(function(step) {
    this.numA += step
  }),
  updateNumB: action(function(step) {
    this.numB += step
  }),
})

 Bind members in the Store to the page

# 页面的 .js 文件
import { createStoreBindings } from 'mobx-miniprogram-bindings'
import { store } from './store'
Page({
  onLoad() {
    this.storeBindings = createStoreBindings(this, {
      store,
      fields: ['numA', 'numB', 'sum'],
      actions: ['updateNumA']
    })
  },
  <!-- 生命周期函数--监听页面卸载 -->
  onUnload() {
    this.storeBindings.destroyBindings()
  }
})

 Use members from the Store on your page

# 页面的 .wxml
<view>{
   
   {numA}} + {
   
   {numB}} = {
   
   {sum}}</view>
<van-button type="primary" bindtap="btnHandler" data-step="{
   
   {1}}">numA + 1</van-button>
<van-button type="primary" bindtap="btnHandler" data-step="{
   
   {-1}}">numA - 1</van-button>
<!-- 按钮 tap 事件的处理函数 -->
btnHandler(e) {
  this.updateNumA(e.target.dataset.step)
}

 Bind members from the Store to components

import { storeBindingsBehavior } from 'mobx-miniprogram-bindings'
import { store } from './store'
Component({
  behaviors: [storeBindingsBehavior],
  storeBindings: {
    store,
    fields: {
      numA: () => store.numA,
      numB: (store) => store.numB,
      sum: 'sum'
    },
    actions: {
      updateNumA: 'updateNumA'
    }
  }
})

 Use Store members in components

# 组件的 .wxml 结构
<view>{
   
   {numA}} + {
   
   {numB}} = {
   
   {sum}}</view>
<van-button type="primary" bindtap="btnHandler" data-step="{
   
   {1}}">numA + 1</van-button>
<van-button type="primary" bindtap="btnHandler" data-step="{
   
   {-1}}">numA - 1</van-button>
<!-- 按钮 tap 事件的处理函数 -->
btnHandler(e) {
  this.updateNumA(e.target.dataset.step)
}

 

Guess you like

Origin blog.csdn.net/lwf3115841/article/details/132819871