最近来个需求,要求给小程序的 modal 增加个关闭按钮,上网一查发现原来 2018 年就有人给出解决方案了,于是总结下微信小程序自定义组件的思路:一句话,用 wxml + css实现和原生组件类似的样式和效果,之后用 JS 实现类似原生组件的功能。
比如 modal 组件,观察可以得出就是个在页面顶层显示的 mask + div。modal 的显示与否可以通过 wx-if 控制,需要注意的点是 modal 显示的时候要有动画效果,这个功能可以通过 css animation 实现。
自定义 modal 的示例代码:
WXML:
html
<view wx-if="{{cusModalShow}}" bindtap="handleCusModalMaskTap" class="cus-modal">
<view catchtap class="cus-modal__content">
<view class="cus-modal__close-btn" bindtap="handleCusModalMaskTap">
×
</view>
<view class="cus-modal__content-title">
<text>提示</text>
</view>
<view class="cus-modal__content-text">
<text>请确认操作</text>
</view>
<view class="cus-modal__content-buttons">
<text bindtap="handleCusModalCancel" class="cus-modal__content-button-cancel">取消</text>
<text bindtap="handleCusModalConfirm" class="cus-modal__content-button-confirm">确认</text>
</view>
</view>
</view>
CSS:
css
@keyframes fade-in {
0% {
opacity: 0;
}
100% {
opacity: 1;
}
}
.cus-modal {
display: flex;
align-items: center;
justify-content: center;
position: fixed;
top: 0;
left: 0;
width: 100%;
height: 100%;
background: rgba(0, 0, 0, 0.6);
animation: fade-in 0.3s ease;
}
.cus-modal__content {
background-color: white;
border-radius: 15px;
width: 80%;
position: relative;
}
.cus-modal__close-btn {
color: rgb(179, 179, 179);
font-size: 1.5rem;
position: absolute;
right: 0.5rem;
top: 0.1rem;
}
.cus-modal__content-title,
.cus-modal__content-text {
font-size: 1.1rem;
text-align: center;
}
.cus-modal__content-title {
font-weight: bold;
margin: 40px 0 20px 0;
}
.cus-modal__content-text {
color: rgb(179, 179, 179);
margin-bottom: 40px;
}
.cus-modal__content-buttons {
display: flex;
}
.cus-modal__content-buttons {
border-top: 1px solid rgb(245, 245, 245);
}
.cus-modal__content-buttons>text {
flex: 1;
text-align: center;
padding: 20px 30px;
border-right: 1px solid rgb(245, 245, 245);
box-sizing: border-box;
height: 60px;
}
.cus-modal__content-buttons>text:last-child {
border-right: none;
}
.cus-modal__content-button-cancel {
font-weight: bold;
}
.cus-modal__content-button-confirm {
font-weight: bold;
color: rgb(90, 117, 155);
}
自定义 Picker:
这里实际只是模拟了原生 Picker 从底部弹入的效果,具体内容可以通过放在里面的组件实现。
WXML
html
<view bindtap="closeBottomPicker" wx-if="{{cusPickerShow}}" class="cus-picker">
<view class="cus-picker__mask"></view>
<view catchtap class="cus-picker__content">
<!-- <view class="cus-picker__header">
<text class="cus-pick__header__btn-cancel">取消</text>
<text class="cus-pick__header__btn-confirm">确定</text>
</view> -->
<some-component bindclose="handleCarFilterClose"></some-component>
</view>
</view>
CSS:
css
@keyframes slide-up-from-bottom {
0% {
transform: translateY(100%);
}
100% {
transform: translateY(0);
}
}
@keyframes fade-in {
0% {
opacity: 0;
}
100% {
opacity: 1;
}
}
.cus-picker {
z-index: 114514;
position: fixed;
top: 0;
left: 0;
width: 100%;
height: 100%;
}
.cus-picker__mask {
position: absolute;
width: 100%;
height: 100%;
left: 0;
top: 0;
background-color: rgba(0, 0, 0, 0.5);
animation: fade-in 0.3s ease;
}
.cus-picker__content {
box-sizing: border-box;
position: absolute;
height: 50%;
width: 100%;
bottom: 0;
background-color: white;
animation: slide-up-from-bottom 0.3s ease;
}
.cus-picker__header {
display: flex;
justify-content: space-between;
padding: 20px;
border-bottom: 1px solid rgb(245, 245, 245);
font-size: 16px;
}
.cus-pick__header__btn-cancel {
color: rgb(127, 127, 127);
}
.cus-pick__header__btn-confirm {
color: rgb(0, 196, 105);
}