“This is the fifth day of my participation in the Gwen Challenge in November. Check out the details: The Last Gwen Challenge in 2021.”

1, the background

In the process of mobile terminal development, it is often encountered that some operations need to be performed in the pop-up box at the bottom of the page, as shown in the following figure:

This uses the picker component of the bottom pop-up box provided by wechat mini program

Base library 1.0.0 to start support, earlier versions need to do compatibility processing.

Scroll selector that pops up from the bottom.

But sometimes we need to customize the content of the bottom box, this time we need to define a bottom box component.

2. Implementation principle

2.1 Realization of the effect drawing

As you can see from the above renderings, when we click on the pop-up bottom dialog, a mask layer pops up over the top of the current page, which is then displayed through some animation and style effects.

The pop-up dialog box at the bottom is close to the effect of picker provided by wechat official.

The top provides “cancel” and “OK” buttons. When clicking the “Cancel” and “OK” buttons on the page, the popbox will disappear.

As for the content in the middle of the popbox, you can define it yourself. I put a device list in this place, and I will check the box when I select the device list.

2.2 Code Implementation

For details about user-defined components in the applet, see the official document of the applet official website

Take a look at the implemented component directory structure:

As you can see, a custom component is also composed of json, WXML, WXSS, JS files, similar to a page.

Here are the steps to customize a component:

The first step

Making custom component declarations in JSON files (setting the Component field to true makes this set of files custom components) :

{
  "component": true
}
Copy the code

The second step

Define WXML, WXSS, JS, templates, styles, and logical files.

The bottomdialog.wxml code looks like this:

<! --pages/components/bottomdialog/bottomdialog.wxml--> <view wx:if='{{flag}}'> <view class='wrap {{wrapAnimate}}' Style = 'background: rgba (0, 0, {{bgOpacity}}); '></view> <view catchtap='hideFrame' class='frame-wrapper {{frameAnimate}}'> <view catchtap='catchNone' class='frame'> <! <view class='title-wrapper flex'> <view id='oncancle' catchtap=' oncancle' class="title-cancle"> </view> <view  id='onConfirm' catchtap= 'onConfirm' class="title-confirm">{{frameTitle}}</view> </view> <! <slot></slot> </view> </view> </view>Copy the code

The layout code is relatively simple, defining the style and animation, and the content part contains the header and content two parts.

The header mainly defines two view cancellations, identified to handle click events.

The content section uses a ‘slot’ slot for customizing the content layout.

Look at the style bottomDialog.wxSS code below:

/* pages/components/bottomdialog/bottomdialog.wxss */ .wrapAnimate{animation: WrapAnimate 0.5s ease-in-out forward} @keyframes wrapAnimate{0%{} 100%{background: Rgba (0, 0, 0, 0.35); } } .wrapAnimateOut{animation: WrapAnimateOut 0.4s ease-in-out forward} @keyframes wrapAnimateOut{0%{background:rgba(0,0,0,0.35); } 100%{background:rgba(0, 0, 0, 0); FrameAnimate {animation: frameAnimate 0.5s ease forward; } @keyframes frameAnimate{ 0%{} 100%{opacity: 1; top:0vh; }}. FrameAnimateOut {animation: frameAnimateOut 0.4s ease forward; } @keyframes frameAnimateOut{ 0%{opacity: 1; top:0vh; } 100%{opacity: 0; top:100vh; } } .frame-wrapper{position: fixed; height:100vh; width:100vw; z-index: 2; top: 50vh; } .frame{background: #fff; position: absolute; bottom: 0; Width: 88.2 vw; Padding: 5.9 vw 5.9 vw 0; border-top-left-radius: 20rpx; border-top-right-radius: 20rpx; z-index: 3; } .title-wrapper{justify-content: space-between; The font - size: 4.9 vw; color: #4a4a4a; Margin - bottom: 5.9 vw; }. The title - wrapper > image {width: 3.2 vw; Height: 3.2 vw; padding:0 5vw; margin-right:-5vw; } .flex{display: flex; align-items: center; } .wrap{position: fixed; z-index: 1; top: 0; left: 0; right: 0; bottom: 0; } .title-cancle{ font-size: 28rpx; color: #000000; } .title-confirm{ font-size: 28rpx; color: #4063E7; }Copy the code

Styles use CSS attributes such as KeyFrames

This property is closely related to the animation property. Keyframes is translated into Chinese, which means “keyframe”. The animation property can use @keyframes to divide the animation within a specified period of time into more details.

Grammatical structure:

@keyframes animationname {keyframes-selector {css-styles; }}Copy the code

Animationname: Specifies the name of the animation. 2. Keyframes -selector: Used to segment the duration of an animation, either in percentage form or “from” or “to”. The forms “from” and “to” are equivalent to 0% and 100%. Percentages are always recommended.

ease-in-out

Specifies the transition effect ending at a slow speed (equal to cubic-bezier(0,0,0.58,1)) (faster at the beginning and slower at the end, relative to a constant speed,)

opacity

The opacity property specifies the opacity of an element. In other words, the opacity property specifies how much background behind an element is overwritten.

For more information on how to use styles, go to W3shool.

Bottomdialog. Js file

// pages/components/bottomdialog/bottomdialog.js Component({ properties: { }, data: { flag:false, wrapAnimate:'wrapAnimate', bgOpacity:0, frameAnimate:'frameAnimate', }, properties: { frameTitle: { type: String, value: 'title ',}}, methods: {showFrame() {this.setData({flag: true, wrapAnimate: 'wrapAnimate', frameAnimate: 'frameAnimate' }); }, hideFrame(e) { const that= this; that.setData({ wrapAnimate: 'wrapAnimateOut', frameAnimate: 'frameAnimateOut' }); setTimeout(()=>{ that.setData({ flag: false}) },400); }, onCancle(e){ this.hideFrame(e); this.triggerEvent('myCancel'); }, onConfirm(e){ this.hideFrame(e); this.triggerEvent('myConfirm'); }, catchNone(){// prevent bubble}, _showEvent() {this.triggerEvent("showEvent"); }, _hideEvent() { this.triggerEvent("hideEvent"); }}})Copy the code

The logic code mainly controls the display and hiding of the bottom frame, and the event processing of the head button.

Now that’s the main code, let’s look at how this component is used.

3. Use of components

It’s also easy to use custom components in applets. You just need to introduce custom components in the.json file of the page.

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

Where “BottomDialog” can be defined by itself, which is the name used when using the component in a WXML file.

3.1 Using custom components in WXML files

<! </ bottomDialog id="bottomFrame" frameTitle=" " bindmyConfirm="onConfirm" bindmyCancel="onCancel"> <scroll-view scroll-y="true" style="height: 400rpx;" > <block wx:if="{{deviceList.length > 0}}"> <block wx:for="{{deviceList}}"> <view class="body-content" id="bodyitem" bindtap="chooseItem" data-index="{{index}}"> <view></view> <text>{{item.name}}</text> <image wx:if="{{item.isCheck}}" src="/image/administrators_check.png" ></image> <image wx:else ></image> </view> </block> </block> <block wx:else> <view Class ="nodata"> </view> </block> </scroll-view> </bottomdialog>Copy the code

You can see that while using BottomDialog, you have added the frameTitle property, bindmyConfirm, bindmyCancel event handling, and added a scrool-View component, which will be displayed in the content of the custom component.

Note: Events in custom components need to be handled with bind+ event names where used to retrieve events in custom components on pages that use custom components.

3.2 Use of custom components in logical files

// pages/test02/test02.js Page({/** **) {deviceList:[{name:" deviceList ", isCheck: False}, {name:" device 02", isCheck: false}, {name:" device 03", isCheck: false}, {name:" device 04", isCheck: false}, {name:" device 04", isCheck: False}, {name:" device 05", isCheck: false}],}, /** * lifecycle function -- listen to page load */ onLoad: function (options) {}, onClick: function(e){ this.selectComponent('#bottomFrame').showFrame(); }, chooseItem: function(e){ let index = e.currentTarget.dataset.index; this.setData({ ['deviceList[' + index + '].isCheck']:! This.data.devicelist [index].ischeck}) console.log(" click :", this.data.devicelist [index].name)}, Wx.showtoast ({icon:"none", title: 'click on the cancel'}}), / / click ok after onConfirm () {wx. ShowToast ({icon: "none", the title: 'click the confirm,})},})Copy the code

SelectComponent (‘#bottomFrame’) to get the instance of the custom component.

Once you get the instance, you can call the methods in your custom component.

In addition, we have implemented onCancel and onConfirm methods in the page code.

3.3 Style Code

/* pages/test02/test02.wxss */

.body-content{
    display: flex;
    padding: 10rpx;
    height: 50rpx;
    align-items: center;
    justify-content: space-between;
  }

  
.nodata{
    display: flex;
    justify-content: center;
    align-items: center;
    font-size: 24rpx;
    color: #bebbbb;
    margin-top: 80rpx;
  }

  image{
    width: 20rpx;
    height:20rpx;
  }
Copy the code

PNG administrators_check. PNG

Well, hopefully you found that helpful.