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
wxml
Data 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 pass
This.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.detail
Can 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)Number
The stringString
Boolean (,Boolean
) and complex data types (objectsObject
An 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 as
id
.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, passes
triggerEvent
Fires the custom event name in the parent component, and at the same time,triggerEvent
The second parameter is to carry the required data - Methods defined in the parent component pass through the event object
event.detail
To get the value passed in the child component - In the parent component, re
setData
The 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 passes
this.selectComponent
Get 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 it
view
thebindtap
Event?
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/