微信小程序通用弹窗组件封装与动画实现
在微信小程序开发中,弹窗是常见的交互方式。官方并没有提供通用的 Dialog
组件,我们通常需要手写 view
并控制 show/hide
来实现,但这样会造成代码重复、维护不便。
本文将带你从零开始封装一个 通用的弹窗组件,支持以下特性:
多种位置:顶部 / 中间 / 底部 / 左边 / 右边;
动画效果:滑入 / 滑出、淡入 / 淡出;
遮罩层:支持开启/关闭、点击关闭;
插槽机制:弹窗内部内容可灵活替换;
高复用性:页面只需简单调用即可。
一、组件文件结构
新建 components/popup/
文件夹,结构如下:
/components/popup/popup.wxml # 组件结构popup.wxss # 组件样式popup.js # 组件逻辑popup.json # 组件声明
二、popup.json
组件声明文件,标识这是一个自定义组件:
{"component": true,"usingComponents": {}
}
三、popup.wxml
结构上分为两部分:
遮罩层(点击可关闭);
弹窗内容(支持插槽传入自定义内容)。
<view wx:if="{{visible}}"><!-- 遮罩层 --><viewclass="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
样式包括遮罩层、不同位置的初始样式,以及显示/隐藏时的过渡动画。
/* 遮罩层 */
.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
逻辑部分主要是 属性定义 和 遮罩点击事件处理。
Component({properties: {// 是否显示弹窗visible: {type: Boolean,value: false},// 位置: top / center / bottom / left / rightposition: {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
中引入:
{"usingComponents": {"popup": "/components/popup/popup"}
}
2. 页面 WXML
<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
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
方法关闭所有弹窗。
七、总结
本文实现了一个 通用弹窗组件,支持:
位置灵活:顶部、中间、底部、左、右五种方式;
交互自然:支持遮罩层和点击遮罩关闭;
动画平滑:滑入滑出、缩放淡入淡出效果;
高度复用:通过插槽自定义内容,适配不同业务场景。
在实际项目中,你可以在此基础上扩展更多功能,例如:
确认/取消按钮,做成标准的对话框;
抽屉效果,用于侧边栏菜单;
表单弹窗,用于收集用户输入。
通过封装组件,既能提高代码复用率,也能让交互体验更加统一和专业。 🚀