WeChat Mini Program: Data transfer of custom components

WeChat Mini Program: Data transfer of custom components

Reprinted link address:[https://segmentfault.com/a/1190000014474289?utm_source=index-hottest](https://segmentfault.com/a/1190000014474289?utm_source=index-hottest)

I. Introduction

If there is a reusable UI and certain functionality in the applet, you can use custom components to encapsulate it. (If you only need to reuse the UI, you can use template) The following describes the data transfer method of parent and child components, as well as an example of a simple component and a complex component.
[Because when I first wrote this article, I was still a novice in a small program. I looked at the official documents to study and summarize, there are many shortcomings and errors. After a year of precipitation (although this year I am mainly writing vue rather than small programs), I decided to reorganize this article with a relatively large number of views, so as to prevent novices from making detours due to my article.

Second, the method of transferring data between parent and child components

1. The parent component passes data to the child component
parent.wxml

<my-component name="{
   
   {name}}" age="{
   
   {age}}"></my-component>

parent.js

data: {
  name: 'Peggy',
  age: 25
}

child.js

properties: {
  name: {
    type: String,
    value: '小明'
  },
  age: Number
}

The parent component passes the value to the child component in the form of properties, and the child component receives it in properties, and can specify the data type type and the default value value.
It can be used directly in the form of { {name}} in wxml, and obtained as this.properties.name in js.

2. The child component passes the value
child.js to the parent component

methods: {
  changeName() {
    this.triggerEvent('changeName', {
      name: '李四'
    })
  }
}

parent.wxml

<my-component name="{
   
   {name}}" age="{
   
   {age}}" bindchangeName="changeName"></my-component>

parent.js

changeName(event) {
  console.log(event.detail)
  // { name: '李四' }
}

The child component passes data to the parent component using the this.triggerEvent method, this method accepts 3 parameters:
this.triggerEvent('myevent', myEventDetail, myEventOption);

myevent is the method name,
myEventDetail is the data passed to the outside of the component,
myEventOption is the option of bubbling or not, there are three parameters that can be set:

bubbles    默认false 事件是否冒泡
composed 默认false 事件是否可以穿越组件边界
capturePhase 默认false 事件是否拥有捕获阶段

The parent component listens to the event bindchangeName="changeName". There is an event parameter in the changeName method, and the value passed from the component can be obtained from event.detail.

3. Simple components (counters)

Insert picture description here
1. Component function introduction
This component is commonly used in takeaway software to record the quantity of goods you want to buy. When initializing, there is only one plus sign. After clicking the plus sign, a number and a minus sign will appear, and finally the number will be transmitted to the component for external use.

2. Create components
First create the components folder (recommended) in the root directory, then create the num-controller folder (the component name I took), right-click on this folder to create a new component, the name is index.
Insert picture description here
/components/num-controller/index.wxml

<view class="num-controller">
  <image src="images/minus.png" class="{
   
   {num <= min ?'hide': ''}}" bindtap="sub"></image>
  <text class="num">{
   
   {num}}</text>
  <image src="images/plus.png" bindtap="add"></image>
</view>

This code is to add and subtract two buttons and a number.
/components/num-controller/index.json

{
  "component": true,
  "usingComponents": {}
}

This file will automatically write this code when creating the component.
/components/num-controller/index.js

Component({
  /**
   * 组件的属性列表
   */
  properties: {
    nameId: {
      type: String
    },
    num: {
      type: Number,
      value: 0
    },
    int: {
      type: Number,
      value: 1
    },
    min: {
      type: Number,
      value: 0
    }
  },

  /**
   * 组件的初始数据
   */
  data: {

  },

  /**
   * 组件的方法列表
   */
  methods: {
    numChange() {
      this.triggerEvent('numChange', {
        num: this.properties.num,
        nameId: this.properties.nameId
      })
    },
    add() {
      this.setData({
        num: this.properties.num + this.properties.int
      })
      this.numChange()
    },
    sub() {
      this.setData({
        num: this.properties.num - this.properties.int
      })
      this.numChange()
    }
  }
})

I defined 4 properties inside the component, properties are the properties passed from the parent component to the child component.
The nameId is used to identify the uniqueness of the child component. If there are multiple counters in the parent component, it can be used when the child component wants to pass the changed data to the parent component;
num represents the number in the counter, and the default is 0;
int represents addition How much to change at one time, the default is 1;
min represents the minimum value of the counter, the minus sign will disappear when it is equal to this value, and the default is 0.

At the same time, two methods are defined in the sub-component:
add click the plus sign to trigger, first change the number inside the sub-component, and at the same time trigger the numChange method to transfer the changed number to the outside of the component;
sub click the minus sign to trigger, first change the internal sub-component Number, at the same time trigger the numChange method to pass the changed number to the outside of the component.

3. Introduce components
If I want to introduce components in index.wxml:

<num-controller nameId="num1" num="{
   
   {num1}}" bindnumChange="numChange"></num-controller>
<num-controller nameId="num2" num="{
   
   {num2}}" int="{
   
   {5}}" min="{
   
   {5}}" bindnumChange="numChange"></num-controller>
<num-controller nameId="num3" num="{
   
   {num3}}" int="{
   
   {100}}" bindnumChange="numChange"></num-controller>

index.json

{
  "usingComponents": {
    "num-controller": "/components/num-controller/num-controller"
  }
}

If you want to use the component in the page, you must register the component in the json file.
index.js

Page({
  data: {
    num1: 0,
    num2: 10,
    num3: 100
  },
  numChange(event) {
    const {num, nameId} = event.detail
    this.setData({
      [nameId]: num
    })
  }
})

The num1, num2, and num3 in data are num passed in from outside the component. In the numChange method, event.detail can be used to get the data passed through this.triggerEvent inside the component, and then make logical modifications according to business requirements.

Fourth, complex components (filter panel)

Insert picture description here
This is a secondary menu. Clicking on the left (level 1) will change the display on the right (level 2).
1. Create a component and import it
inside the component:
/components/filter-panel/index.wxml

<view class="filter-panel">
  <view class="panel-container">
    <view class="panel-left">
      ...
    </view>

    <view class="panel-right">
      ...
    </view>
  </view>
</view>

/components/filter-panel/index.json

{
  "component": true,
  "usingComponents": {}
}

External components:
If I want to introduce components in index.wxml:

<filter-panel></filter-panel>

In this way, components have been successfully introduced~ (really, componentization is very comfortable, and it will save a lot of effort later)
2. Data transfer between components and external
(1) Fixed data rendering
External component:
index.wxml

<filter-panel list="{
   
   {list}}" active="{
   
   {active}}"></filter-panel>

index.js

data: {
  list: [
    ['附近', '地铁站'],
    [['不限', '1km', '2km', '3km'], ['江汉路', '积玉桥', '洪山广场', '楚河汉街', '光谷广场']]
  ],
  active: [0, 0]
},

Inside the component:

/components/filter-panel/index.js

Component({
  /**
   * 组件的属性列表
   */
  properties: {
    list: Array,
    active: Array
  },
  /**
   * 组件的方法列表
   */
  methods: {
    ...
  }
})

If you want to transfer data from outside the component to the inside of the component, pass it in as an attribute directly when referencing it externally.
Here I passed in 2 attributes:
list is the data rendered by the secondary selection panel.
active is the option data selected by the user.

Up to this point, the component can be displayed normally, but the selected item has not been realized by clicking to display it.

(2) Variable data rendering
The external data active: [0, 0] that controls the component's active item is passed to the inside in the form of attributes through the component.

/components/filter-panel/index.wxml

<view class="filter-panel">
  <view class="panel-container">
    <view class="panel-left">
      <ul>
        <li 
          class="{
   
   {active[0] == index? 'active': ''}}" 
          wx:for="{
   
   {list[0]}}" 
          wx:key="{
   
   {index}}" 
          wx:index="index" 
          data-index="{
   
   {index}}"
          bindtap="changeLevel1"
        >
          {
   
   {item}}
        </li>
      </ul>
    </view>

    <view class="panel-right">
      <ul>
        <li 
          class="{
   
   {active[1] == index? 'active': ''}}" 
          wx:for="{
   
   {list[1][active[0]]}}" 
          wx:key="{
   
   {index}}" 
          wx:index="index" 
          data-index="{
   
   {index}}"
          bindtap="changeLevel2"
        >
          {
   
   {item}}
        </li>
      </ul>
    </view>
  </view>
</view>

/components/filter-panel/index.js

Component({
  /**
   * 组件的属性列表
   */
  properties: {
    list: Array,
    active: Array
  },
  /**
   * 组件的方法列表
   */
  methods: {
    changeLevel() {
      this.triggerEvent('changeLevel', {
        level1: this.properties.active[0],
        level2: this.properties.active[1]
      })
    },
    changeLevel1(event) {
      const index = event.target.dataset.index
      this.setData({
        active: [index, 0]
      })
      this.changeLevel()
    },
    changeLevel2(event) {
      const level2 = 'active[1]'
      const index = event.target.dataset.index
      this.setData({
        [level2]: index
      })
      this.changeLevel()
    }
  }
})

(3) The data
in the component is transferred to the outside. In this component, I defined the changeLevel method. Every time I click the first-level menu or the second-level menu, I use the this.triggerEvent method to pass the active value to the outside of the component for use.

/components/filter-panel/index.js

 methods: {
      changeLevel() {
        this.triggerEvent('changeLevel', {
          level1: this.properties.active[0],
          level2: this.properties.active[1]
        })
      },
      changeLevel1(event) {
        const index = event.target.dataset.index
        this.setData({
          active: [index, 0]
        })
        this.changeLevel()
      },
      changeLevel2(event) {
        const level2 = 'active[1]'
        const index = event.target.dataset.index
        this.setData({
          [level2]: index
        })
        this.changeLevel()
      }
    }

5. Summary In
this project, the data transfer between components is not used, so it is relatively simple to transfer the components and the outside, but we must think clearly about the changing state of the data.

Reprinted link address:https://segmentfault.com/a/1190000014474289?utm_source=index-hottest

Guess you like

Origin blog.csdn.net/wangyanxin928/article/details/96479333