preface

For component encapsulation, it plays an important role in the reuse of multiple pages in the applet, where each page registered is independent

The display view layer and the logical layer of the page are bound with data. If the data in the page needs to be changed, it is modified by setData

So how do you customize components in applets and how do custom components communicate with each other

Effect of instance

  • The full effect can be seen in the original text

By the end of this article, you’ll have learned from the simple number plus and minus input box component above

  • How do I customize components in applets

  • How do I use custom components in an applet page

  • How does a parent (external) component pass values to its children

  • How does a child receive a value from its parent while rendering the component

  • How do events interact within a child component, and how do you pass data to a parent component, affecting data defined by the parent component

  • Alternatively, the parent component gets the child’s data (not triggerEvent, i.e. SelectComponent)

  • How do I disable a View’s Bindtap event when certain conditions are met

  • Number add and subtract input box code optimization

Why customize components?

Each small program page can be seen as a custom component, when multiple pages appear repeated structure, the same part can be extracted and encapsulated into a common component, different parts, in the page through the way of passing parameters into the component, rendering out, to achieve the purpose of reuse

The following to a simple number plus and minus input box components for example, sparrow is small, but all five organs.

How to use custom components?

Create a Components folder in the miniProgram directory, the same as the Pages directory, which is dedicated to custom components

For example: Create a count folder in the Components directory, and then create a Component named count. Wechat developer tool will automatically create the count Component

As follows:

<view>
  <view class="count-container">
    <view bindtap="reduce" class="{{count == 1? 'btn-disabled': ''}}}">-</view>
    <input bindinput="handleInput" type="number" value="{{count}}" />
    <view bindtap="add">+</view>
  </view>
</view>
Copy the code

Here is the CSS code

/* components/count/count.wxss */
.count-container {
  width: 200rpx;
  display: flex;
  justify-content: center;
  border: 1px solid #ccc;
  margin: 30px auto;
}

.count-container view {
  width: 30px;
  text-align: center;
}

.count-container view:nth-child(1) {
  border-right: 1px solid #ccc;
}
.count-container view:nth-child(3) {
  border-left: 1px solid #ccc;
}

.count-container input {
  flex: 1;
  text-align: center;
}

.btn-disabled {
  background: #eee;
  pointer-events: none; /* wechat applet View disallows the bindtap event to block clicks, which is a cSS3 property specifying under what circumstances an element can be a target for mouse events (including the style of the mouse) */
}
Copy the code

Here is the JS logic code

// components/count/count.js
Component({
  /** * Component property list */
  properties: {
    count: Number,},/** * The initial data of the component */
  data: {},

  /** * list of component methods */
  methods: {
    reduce() {
      console.log('cut');
      var count = this.data.count - 1;
      if (count < 1) {
        count = 1;
      }
      this.setData({
        count,
      });
      this.triggerEvent('changeCount', count);
      console.log(this.data.count);
    },

    add() {
      console.log('and');
      var count = this.data.count + 1;
      this.setData({
        count,
      });
      this.triggerEvent('changeCount', count);
      console.log(this.data.count);
    },

    handleInput(event) {
      console.log(event);
      this.setData({
        count: event.detail.value,
      });
      this.triggerEvent('changeCount', event.detail.value); ,}}});Copy the code

Now that the custom component is defined, how do you use it

In the Pages directory, here I create a customComponents page

Customize the name of the component using usingComponents in the customComponents. Json file corresponding to the page, and import the component’s path

{
  "usingComponents": {
    "count":"/components/count/count"}}Copy the code

Pay attention to

Importing components: It is also possible to use a relative path, such as the root path /, and customize component names to be case-sensitive. For code readability, you are advised to use lowercase letters and hyphens between multiple letters, such as count-number

This is preceded by the name of the custom component, followed by the declaration of the path to create the component

  "usingComponents": {
    "count":".. /.. /components/count/count"
  }
Copy the code

Then call the component directly from the parent (external) WXML of the corresponding page (in this case customComponents) and insert it as a tag

You can think of custom components as custom tags, an extension of views in native WXML, on which you can add custom properties and bind custom events.

See the sample code below

<count count="{{countNum}}" bind:changeCount="handleCount"></count>
<view class="parentText">The parent component count: {{countNum}}</view>
Copy the code

In the logic code in the customComponents custom page, look like this

// pages/customComponents/customComponents.js
Page({
  /** * initial data for the page */
  data: {
    countNum: 1,},/** * lifecycle function -- listens for page loading */
  onLoad: function(options) {},

  // Events for custom bindings in the parent component
  handleCount(event) {
    this.setData({
      countNum: event.detail, }); }});Copy the code

In wechat small program, the use of components is so simple, want to use in which page, in which page xxx.json declaration component, it is ok

The above code may look a bit silly, but it will be broken down step by step.

Communication and events of components in applets

In applets, there are several basic ways to communicate between components

  • wxmlData binding: Used by a parent component to specify property setting data to a child component (this will be covered in a separate section later)
  • Events: used to transfer data to the parent component sub components and transfer any data (listen for an event is one of the main methods of communication components, custom components can trigger any event, the page reference component can be monitored, these events to monitor the custom component based component method and monitoring events method completely consistent)
  • If neither option is available, the parent component can passThis.selectcomponent (" Class name or ID")Method to get the instance object of the child component so that it does not have to pass in the parent componentevent.detailCan directly access any data and methods of the child component (also mentioned later).

How do I pass data into a custom component?

In the WXML of the customComponents page, reference the count component as a label

This page, which can be viewed as a parent component, can define the data, methods, and so on of the current component, as shown below

<count count="{{countNum}}" bind:changeCount="handleCount"></count>
Copy the code

The data defined in the parent component can also be treated as external data. For example, the above countNum is mounted under data in customComponents, with the initial value countNum equal to 1

The parent (external) component passes data to the child (inner) component by defining custom properties on the child, which can be primitive data types (numbers)NumberThe stringStringBoolean (,Boolean) and complex data types (objectsObjectAn array,Array)

As in this example, the count component defines the count property, which is not a fixed name, and the custom changeCount method

That is, we assign the countNum variable object to the count property and customize the changeCount method to the count component

Pay attention to

The handleCount method is defined in the parent component

// Events for custom bindings in the parent component
  handleCount(event){
    this.setData({
      countNum: event.detail  The parent component's countNum will not update the synchronization unless countNum is reset})}Copy the code

How does a child receive a value from its parent?

Within a child Component, the Component constructor can be used to define the Component, specifying its properties, data, methods, and so on when called

The Properties object receives custom property data from external (parent) components, which can be objects, arrays, primitive data types, and so on

Data is the private variable data that defines the current component and can be used for rendering component templates

Warm prompt

Whether variable data objects are defined under Properties or mounted under data depends on the use of the component

Any data that is passed in externally is placed in properties, while the current (internal) component template rendering is mounted under Data

The data mounted below this data is divided into ordinary data fields and pure data fields, where the latter pure data field variable starts with _

These specified pure data fields require a pureDataPattern regular expression to be specified in the Options object of the Component constructor. Fields whose names match this regular expression become pure data fields

In the small program component, in some cases, some fields in data, including setData set fields, some only participate in the business logic, will not be displayed on the interface, will not be passed to other components, only used within the current component

Such data fields are called pure data fields and can be defined in a global scope or under data. If defined under data, they are recorded in this.data and do not participate in any interface rendering process

As shown below.

Component({
  options: {
    pureDataPattern: / / ^ _.// Specify that all data fields starting with _ are pure data fields
  },
  data: {
    a: true.// Common data fields
    _b: true.// Pure data field
  },
  methods: {
    myMethod() {
      this.data._b; // Pure data fields can be retrieved in this.data
      this.setData({
        c: true.// Common data fields
        _d: true.// Pure data field}); ,}}});Copy the code

The pure data fields in the above component will not be applied to WXML

<view wx:if="{{a}}">The line will be shown</view>
<view wx:if="{{_b}}">This line will not be shown</view>
Copy the code

::: Receives data from external components in the Properties object

// components/count/count.js
Component({
  /** * Component property list */
  properties: {
    count: Number.Passed here / / receiving external components properties, determine the type of data passed at the same time, the type is String, Boolean, Object, Array, etc
  },

  /** * The initial data of the component */
  data: {},

  /** * list of component methods */
  methods: {},});Copy the code

How to render in an internal component? Just bind the variable object under Properties to the WXML’s {{}} interpolation, as shown below

<view>
  <view class="count-container">
    <view>-</view>
    <input type="number" value="{{count}}" />
    <view>+</view>
  </view>
</view>
Copy the code

This completes the process by which the child component receives the value passed from outside the parent component and renders it in the component

So if you want to manipulate the current component’s data, dynamically manipulate the add and subtract input boxes and bind the corresponding event operations to the component elements

<view>
  <view class="count-container">
    <view bindtap="reduce" class="{{count == 1? 'btn-disabled': ''}}}">-</view>
    <input bindinput="handleInput" type="number" value="{{count}}" />
    <view bindtap="add">+</view>
  </view>
</view>
Copy the code

Bindtap method is added on + and – to process business logic, as shown below

// components/count/count.js
Component({
  /** * Component property list */
  properties: {
    count: Number,},/** * The initial data of the component */
  data: {},

  /** * list of component methods */
  methods: {
    / / subtraction operation
    reduce() {
      console.log('cut');
      var count = this.data.count - 1;
      if (count < 1) {
        count = 1;
      }
      this.setData({
        count,
      });
    },
    / / add operation
    add() {
      console.log('and');
      var count = this.data.count + 1;
      this.setData({
        count,
      });
    },

    // Listen for form input
    handleInput(event) {
      console.log(event);
      this.setData({
        count: event.detail.value, }); ,}}});Copy the code

How does a child component pass data to its parent, affecting data defined by the parent

Small program, components and components are isolated from each other, independent, through the above operation, the addition and subtraction of the digital framework has indeed been realized, but if the external component, want to get the data in the child component, if not through some means, the child component of the data is not affected by the parent component

Because the transmission of data in the applet is one-way, that is, the parent component passes data to the child component by adding custom properties on the component, and receiving custom component properties in the child component

If you look at frameworks like Vue and React, you’ll see striking similarities. Vue is props for receiving, and React is this.props for receiving

Applets borrow their ideas.

The parent wants to get data from the child. In other words, how does the child pass data to the parent? What if it affects initialization data defined in the parent component

The parent component wants to access the child component’s data by binding custom listening events to the component

Listen for an event

  • Events are the communication mode from the view layer to the logical layer
  • User behavior can be fed back to the logical layer for processing
  • It can be bound to a component, and when a triggering event is reached, the corresponding event handler in the logical layer is executed
  • Event objects can carry additional information such asid.dataset.touches

Event system is one of the main ways of communication between components. A custom component can trigger arbitrary events that can be listened for by a page referencing the component in exactly the same way as the underlying component

As shown below.

<! Call onMyEvent when the custom component fires the myevent event -->
<component-tag-name bindmyevent="onMyEvent" />
<! -- or we could write -->
<component-tag-name bind:myevent="onMyEvent" />
Copy the code

In this example, as shown below,bind:changeCount=”handleCount” binds a custom changeCount event Listening on the count component binds a changeCount event, and when the changeCount event is triggered, the handleCount method defined in the later parent component is called

<count
  class="count"
  count="{{countNum}}"
  bind:changeCount="handleCount"
></count>
Copy the code

In the parent component, the handleCount method is declared, and the event event object is used to retrieve data from the child component

Page({
  handleCount: function(event) {
    event.detail; // Customize the detail object provided when the component fires an event}});Copy the code

Since you listen for a custom event in the parent component, how does that event get triggered inside the child component

Triggering event

When a custom component fires an event, you need to use the triggerEvent method, specifying the event name, detail object, and event options

As shown below.

Component({
  properties: {},
  methods: {
    onTap: function() {
      var myEventDetail = {}; The detail object is provided to the event listener function
      var myEventOption = {}; // The option to trigger the event
      this.triggerEvent('Custom event name myEvent', myEventDetail, myEventOption); ,}}});Copy the code

In this example:

// components/count/count.js
Component({
  /** * Component property list */
  properties: {
    count: Number,},/** * The initial data of the component */
  data: {},

  /** * list of component methods */
  methods: {
    / /
    reduce() {
      console.log('cut');
      var count = this.data.count - 1;
      if (count < 1) {
        count = 1;
      }
      this.setData({
        count,
      });
      this.triggerEvent('changeCount', count);
    },
    / / add
    add() {
      console.log('and');
      var count = this.data.count + 1;
      this.setData({
        count,
      });
      this.triggerEvent('changeCount', count);
    },
    // Listen on the input box
    handleInput(event) {
      console.log(event);
      this.setData({
        count: event.detail.value,
      });
      this.triggerEvent('changeCount', event.detail.value); ,}}});Copy the code

The external component needs to trigger the custom method that the parent component listens to in real time, and the second parameter of the triggerEvent method represents the data that the parent component is passing to the parent component

When the child triggers the changeCount method, the parent component’s handleCount method is called, and the initialization data in the parent component is reset in the parent component to update the synchronized data to the page

Although this process has some around, twists and turns, to beginner, need oneself comprehension, manage

This triggerEvent is equivalent to the this.$emit(‘ bound to the parent’s custom event name ‘) method in vue, as opposed to the this.props method in React. Method, which calls the parent component’s method

Pay attention to

Custom methods that listen on in the parent component (changeCount in the example above) are triggered by a triggerEvent and are placed inside the methods to listen on within the child component rather than defined in the methods method

changeCount() { // This is the wrong way to write a custom method. Some people mistakenly think that a custom method must be written in the form of a method, which is just a name

}
Copy the code

How does a child component pass data to its parent, affecting the data defined by the parent

The child component wants to pass data to the parent, affecting the parent’s initialization of the defined data

  • You first need to set up the listening custom method on the custom component on the parent component
  • In the event method inside the child component, passestriggerEventFires the custom event name in the parent component, and at the same time,triggerEventThe second parameter is to carry the required data
  • Methods defined in the parent component pass through the event objectevent.detailTo get the value passed in the child component
  • In the parent component, resetDataThe data updates the data initialized in the parent component and is rendered to the page

TriggerEvent triggerEvent triggerEvent triggerEvent triggerEvent triggerEvent triggerEvent triggerEvent triggerEvent triggerEvent triggerEvent

In fact, there is another easy way, also can get

The parent component passesthis.selectComponentGet the data in the child component

The premise condition

You need to add a class or ID to a custom component that references the parent component

For example, add a class count to the count component

<count
  class="count"
  count="{{countNum}}"
  bind:changeCount="handleCount"
></count>
Copy the code

So, call this.selectComponent in the parent component’s handleCount to get instance data for the child component

Call with a matching selector, either class or Id, such as this.selectComponent(‘ class or Id ‘).

In this case, this.selectComponent(‘.count’), as shown in the sample code below

 handleCount(){
    console.log(this.selectComponent('.count'));
    var count = this.selectComponent('.count');
    this.setData({
      countNum: count.data.count  // reassign setData countNum data})}Copy the code

This method is also possible and is commonly used in small programs

How to ban itviewthebindtapEvent?

If you want to disable the state for subtracting to a certain value when you do a number addition or subtraction input box, you can either change the View to button when you have a similar situation

It is also ok to set the button’s state to Disabled when a condition is reached

But how do you do that without a button

If you use a View instead of a button, you can get style-disabled under certain conditions, but if you’re testing, the subtraction will still be triggered

This is obviously a bit of a chicken

To solve this problem, use a handy feature in CSS3 to add pointer-events: None to the specified class

.btn-disabled {
  pointer-events: none; /* wechat applet View disallows the bindtap event to block clicks, which is a cSS3 property specifying under what circumstances an element can be a target for mouse events (including the style of the mouse) */
}
Copy the code

This property, applied to the view, blocks bindTap clicks

Number add and subtract input box code optimization

The number addition and subtraction box component is implemented on top of this, which is subtracted separately, and two methods are bound to triggerEvents multiple times

<view>
  <view class="count-container">
    <view
      bindtap="handleCount"
      data-count="1"
      class="{{count == 1? 'btn-disabled': ''}}}"
      >-</view
    >
    <input bindinput="handleInput" type="number" value="{{count}}" />
    <view bindtap="handleCount" data-count="1">+</view>
  </view>
</view>
Copy the code

Bind the same event method handleCount in the above addition and subtraction, and determine whether the addition or subtraction is in the logical code by setting the data-xx attribute

methods: {
  handleCount(event){
      var count = event.currentTarget.dataset.count;
      count  = this.data.count+Number(count);  // We want to convert count to Number, because the custom attribute count is a string, and the + + string concatenation becomes a string
      if(count < 1) {
        count = 1;
      }
      this.setData({
        count: count
      })
      this.triggerEvent('changeCount', count); }},Copy the code

The code above is much simpler and more comfortable to look at than the previous code

When doing business logic like this, you can optimize your code in this way

conclusion

This article focuses on how to communicate between parent and child components in applets. The parent component passes data to the child by binding custom properties to the reference component

The child component receives data in the Properities object, how the child passes data to the parent component, which listens for custom events by binding to the reference component, and then fires custom event names in the child component’s event method, which can carry data from the child component. In a function in the parent component

The event. Detail method is used to retrieve the value passed from the child to the parent, so that the setData data can be reconfigured to update the initialization data in the parent

Although this relationship is a little convoluted, its importance is self-evident.

A link to the

  • Intercomponent communication and events
  • Events in applets
  • Source: https://coder.itclan.cn/