在微信小程序开发中,弹窗是常见的交互方式。官方并没有提供通用的 Dialog
组件,我们通常需要手写 view
并控制 show/hide
来实现,但这样会造成代码重复、维护不便。
本文将带你从零开始封装一个 通用的弹窗组件,支持以下特性:
-
多种位置:顶部 / 中间 / 底部 / 左边 / 右边;
-
动画效果:滑入 / 滑出、淡入 / 淡出;
-
遮罩层:支持开启/关闭、点击关闭;
-
插槽机制:弹窗内部内容可灵活替换;
-
高复用性:页面只需简单调用即可。
一、组件文件结构
新建 components/popup/
文件夹,结构如下:
html
/components/popup/
popup.wxml # 组件结构
popup.wxss # 组件样式
popup.js # 组件逻辑
popup.json # 组件声明
二、popup.json
组件声明文件,标识这是一个自定义组件:
html
{
"component": true,
"usingComponents": {}
}
三、popup.wxml
结构上分为两部分:
-
遮罩层(点击可关闭);
-
弹窗内容(支持插槽传入自定义内容)。
html
<view wx:if="{{visible}}">
<!-- 遮罩层 -->
<view
class="popup-mask"
catchtap="onMaskTap"
style="background-color: {{mask ? 'rgba(0,0,0,0.5)' : 'transparent'}}"
></view>
<!-- 弹窗内容 -->
<view class="popup-content {{position}} {{showAnim ? 'popup-show' : 'popup-hide'}}">
<slot></slot>
</view>
</view>
说明:
-
visible
控制是否渲染; -
mask
控制是否展示遮罩; -
<slot>
插槽用于放置自定义内容。
四、popup.wxss
样式包括遮罩层、不同位置的初始样式,以及显示/隐藏时的过渡动画。
css
/* 遮罩层 */
.popup-mask {
position: fixed;
z-index: 99;
top: 0;
left: 0;
width: 100%;
height: 100%;
}
/* 弹窗基础样式 */
.popup-content {
position: fixed;
z-index: 100;
background: #ffffff;
border-radius: 12rpx;
transition: all 0.3s ease;
opacity: 0;
}
/* 位置样式 */
.top {
top: 0;
left: 0;
width: 100%;
transform: translateY(-100%);
}
.center {
top: 50%;
left: 50%;
transform: translate(-50%, -50%) scale(0.8);
min-width: 60%;
}
.bottom {
bottom: 0;
left: 0;
width: 100%;
transform: translateY(100%);
}
.left {
top: 0;
left: 0;
height: 100%;
width: 70%;
transform: translateX(-100%);
}
.right {
top: 0;
right: 0;
height: 100%;
width: 70%;
transform: translateX(100%);
}
/* 显示动画 */
.popup-show.top,
.popup-show.bottom,
.popup-show.left,
.popup-show.right {
transform: translate(0, 0);
opacity: 1;
}
.popup-show.center {
transform: translate(-50%, -50%) scale(1);
opacity: 1;
}
/* 隐藏动画 */
.popup-hide.top {
transform: translateY(-100%);
opacity: 0;
}
.popup-hide.bottom {
transform: translateY(100%);
opacity: 0;
}
.popup-hide.left {
transform: translateX(-100%);
opacity: 0;
}
.popup-hide.right {
transform: translateX(100%);
opacity: 0;
}
.popup-hide.center {
transform: translate(-50%, -50%) scale(0.8);
opacity: 0;
}
说明:
-
通过
transform
和opacity
实现平移、缩放和透明度过渡; -
popup-show
/popup-hide
类结合transition
实现进场和退场动画。
五、popup.js
逻辑部分主要是 属性定义 和 遮罩点击事件处理。
javascript
Component({
properties: {
// 是否显示弹窗
visible: {
type: Boolean,
value: false
},
// 位置: top / center / bottom / left / right
position: {
type: String,
value: 'center'
},
// 是否显示遮罩
mask: {
type: Boolean,
value: true
},
// 点击遮罩是否关闭
maskClosable: {
type: Boolean,
value: true
}
},
data: {
showAnim: false
},
observers: {
visible(val) {
if (val) {
this.setData({ showAnim: true });
} else {
this.setData({ showAnim: false });
}
}
},
methods: {
onMaskTap() {
if (this.data.maskClosable) {
this.triggerEvent('close'); // 抛出关闭事件
}
}
}
});
说明:
-
visible
控制弹窗开关; -
position
控制位置样式; -
showAnim
用于切换显示/隐藏动画; -
点击遮罩层触发
close
事件,交由页面处理。
六、页面使用示例
1. 引用组件
在页面的 json
中引入:
html
{
"usingComponents": {
"popup": "/components/popup/popup"
}
}
2. 页面 WXML
html
<view class="container">
<button bindtap="openTop">顶部弹窗</button>
<button bindtap="openCenter">中间弹窗</button>
<button bindtap="openBottom">底部弹窗</button>
<button bindtap="openLeft">左侧弹窗</button>
<button bindtap="openRight">右侧弹窗</button>
<!-- 顶部弹窗 -->
<popup visible="{{showTop}}" position="top" bind:close="closeAll">
<view class="popup-inner">这里是顶部弹窗内容</view>
</popup>
<!-- 中间弹窗 -->
<popup visible="{{showCenter}}" position="center" bind:close="closeAll">
<view class="popup-inner">这里是中间弹窗内容</view>
</popup>
<!-- 其他位置同理 -->
</view>
说明:
-
通过
visible
控制弹窗显示; -
position
控制位置; -
内部内容放在
<slot>
中,自由定义。
3. 页面 JS
javascript
Page({
data: {
showTop: false,
showCenter: false,
showBottom: false,
showLeft: false,
showRight: false
},
openTop() {
this.setData({ showTop: true });
},
openCenter() {
this.setData({ showCenter: true });
},
openBottom() {
this.setData({ showBottom: true });
},
openLeft() {
this.setData({ showLeft: true });
},
openRight() {
this.setData({ showRight: true });
},
closeAll() {
this.setData({
showTop: false,
showCenter: false,
showBottom: false,
showLeft: false,
showRight: false
});
}
});
说明:
-
每个按钮打开对应位置的弹窗;
-
closeAll
方法关闭所有弹窗。
七、总结
本文实现了一个 通用弹窗组件,支持:
-
位置灵活:顶部、中间、底部、左、右五种方式;
-
交互自然:支持遮罩层和点击遮罩关闭;
-
动画平滑:滑入滑出、缩放淡入淡出效果;
-
高度复用:通过插槽自定义内容,适配不同业务场景。
在实际项目中,你可以在此基础上扩展更多功能,例如:
-
确认/取消按钮,做成标准的对话框;
-
抽屉效果,用于侧边栏菜单;
-
表单弹窗,用于收集用户输入。
通过封装组件,既能提高代码复用率,也能让交互体验更加统一和专业。 🚀