近日开发微信小程序时,需要一个下拉框的组件,使用和PC端下拉框一样的方式会显得很丑,于是发现微信官方API有个wx.showActionSheet
,但是有诸多限制,例如:最大长度只能是6项,多选等等。
由于业务需要,下面用到下拉框(actionSheet)支持自定义 高度, 选项,单选,多选,以及遮罩层的透明度等参数。
看完效果直接上代码
组件代码
index.js
Component({ properties: { //数据集 options: { type: JSON, value: '' }, //内容层高度 topsHeight: { type: String, value: '40%' }, //遮罩层透明度 opacity: { type: String, value: '0.5' }, //是否单选 IsSingle: { type: Boolean, value: true } }, data: { isShow: false, contentAnimate: null, //内容动画 overlayAnimate: null, //遮罩层动画 }, methods: { /** * 关闭 */ _close: function () { var that = this; this.contentAnimate.bottom("-40%").step(); this.overlayAnimate.opacity(0).step(); this.setData({ contentAnimate: this.contentAnimate.export(), overlayAnimate: this.overlayAnimate.export(), }); setTimeout(function () { that.setData({ isShow: false, }) }, 200) }, /** * 显示 */ _show: function () { var that = this; that.setData({ isShow: true, }) // 容器上弹 var contentAnimate = wx.createAnimation({ duration: 200, }) contentAnimate.bottom(0).step(); //遮罩层 var overlayAnimate = wx.createAnimation({ duration: 250, }) overlayAnimate.opacity(`${this.properties.opacity}`).step(); this.contentAnimate = contentAnimate; this.overlayAnimate = overlayAnimate; this.setData({ contentAnimate: contentAnimate.export(), overlayAnimate: overlayAnimate.export(), }) }, /** * 设置选中 */ _setSelect: function (even) { let data = this.data.options; let index = even.currentTarget.dataset.index; if (this.properties.IsSingle) { data.forEach((item, i) => { if (i == index) { item.Selected = !item.Selected; } else { item.Selected = false; } }); } else { data[index].Selected = !data[index].Selected; } this.setData({ options: data }); }, /** * 确定 * */ _submit: function () { this.triggerEvent('OnSelectFinish', this.properties.options); this._close(); }, /** * 外部方法调用,显示组件 */ showPopup: function () { this._show(); } } })
index.json
{ "usingComponents": {}, "component": true }
index.wxml
<view class="selectComponent" style="height:{{topsHeight}};bottom: -{{topsHeight}};" wx:if="{{isShow}}" animation="{{contentAnimate}}"> <image src="../../images/icon_close_gray.png" class="close" catchtap="_close"></image> <view class="select-ul"> <view class="select-li" wx:for="{{options}}"> {{item.Text}} <block wx:if="{{IsSingle}}"> <view class="checkbox {{item.Selected ? 'singlechecked' : 'singleunchecked'}}" data-index="{{index}}" bindtap="_setSelect"></view> </block> <block wx:else> <view data-single="{{IsSingle}}" class="checkbox {{item.Selected ? 'checked' : 'unchecked'}}" data-index="{{index}}" bindtap="_setSelect"></view> </block> </view> </view> <view class="SubmitBtn" bindtap="_submit"> 确 定 </view> </view> <!-- 遮罩层 --> <view class="overlay" catchtap ="_close" wx:if="{{isShow}}" animation="{{overlayAnimate}}"></view>
index.wxss
.overlay{ position: fixed; top: 0; left: 0; z-index: 1; width: 100%; height: 100%; background-color: rgba(0, 0, 0); } .selectComponent{ background-color: white; position: fixed; /* bottom: -40%; */ left: 0; width: calc( 100% - 100rpx); /* height: 40%; */ z-index: 10000; padding:20rpx 50rpx; border-top-right-radius: 20rpx; border-top-left-radius: 20rpx; } .SubmitBtn{ border-top: 10px #F7F8FA solid; height: 120rpx; text-align: center; line-height: 90rpx; position: absolute; bottom: 0; left: 0; width: 100%; background-color: #4876F9; color: white; } .select-ul{ height: calc( 100% - 200rpx); overflow: auto; margin-top: 50rpx; } .select-li{ text-align: left; line-height: 80rpx; height: 80rpx; position: relative; font-size: 14px; } .checkbox{ top:24rpx !important; right: 30rpx !important; height: 34rpx; } .close{ width: 14px; height: 14px; position: absolute; right: 30rpx; top: 30rpx; } .checkbox{ width: 30rpx; height: 30rpx; top: 58rpx; right: 0rpx; position: absolute; background-repeat: no-repeat; background-size: 30rpx; } .singlechecked{ background-image: url("data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAB4AAAAfCAYAAAGHa02RAAAAAXNSR0IArs4c6QAAAERlWElmTU0AKgAAAAgAAYdpAAQAAAABAAAAGgAAAAAAA6ABAAMAAAABAAEAAKACAAQAAAABAAAAHqADAAQAAAABAAAAHwAAAAD3IR61AAAEhklEQVRIDb1WYWgcRRR+M7ezCUcirUojkvZPpLVIRFJLaxEjFDQb0RYkYFspRawV6y+FS661EKw23IG/asEalFixIgaa2CZ3oQUNaJvSWoVAK2JEREoqtkhbgrd7u+N7c5m92bvtXWNrB+7m7Xvve9/OzHtvFmB+dPcVNpHI6K8rVZA0q9HVW7g4/asvaZCh2oPcnLTXWfLHGCZeWGwV1xaavaL8PqLIZxuYCuqk3LUS5CnTmzF2KZex72NOb2FYSnjeNKIBnF5XqbhI2Du1kQw0tBGjBIqClF0p9xKAXEIyDeIvSca/0+e9ubFfLtKq+FXPo3HBboAhq8OgA641alizsuynNmJgu6VonnyEw+kL5Z1XxvRgET7fI+CbH5HBGLw5ad9Dz5v2eoZaneAM/7KfXVnWZpd2Yd7MGXs9l214oMyOhlcOSvH7jPeHuSFmOAKNZ+wDWqfAPf3y7mtz7mWtrDcjaEYxP7dLtrhFd7YeoGM5g57OBNDiadD5Wa7v/lAL+Hg7g90vCnXo534uAckf85Zb+AoncWfD9DmUFnD5qoTx0wG80WMpkM6WShK15lpHXAnQz5T7CkyKuOzWjuasM550Idh0IFmVm4RHGQQX7UY7N9LP/q70iQVTTrv/uI4Efj+GP5sbEJOVQHqOgLt73Z2BlO/HOaLrn8vaROuHO1iYhyEYd3QWt78lHljWMmCP5bL2FGkU2EkVfsHjaiu71JaoGCjn+bO73I6FACnstTnvL5p50YczJNQbo+8IEKWaRVfJKK05pVk94FfvCpg4G2APLHt6vnsgjFVWR6Vj+wSMfhfA4JgfMeBS10VYqfM1GmV/bEDA8GQ1UEeJgF/KuHBkrw3JRoAxBB4+4cPQRJRRA/GYTmJTduliCIMswX75SdqGoXwRvvg62rA0kGbbwo5OR0WXgWloTtJxmJpKmcl81ub86D77HL7CjGmuDQRoTop7yV+9rupHeLmYAW4kU3pSdoVgEuhWou54I1CpMGxb5zX5hYVhgv5TSZoBtIxtuen6nLcNnzfildOJnS8+sRgrMgmT6DfSlBRDuLTrOkbcHPvWTkq2SvBGMf874kA3r2N4kGJDLsvwEoqOCPEzKbkyYN4U5ttdUbdbe8J+e5VLsXYsyy7oSGFCY4J/5oN7/naTEhHFpNjEESHGL648Gjdr5a3OK5YyrLjqKMRBXGRh3X3uy0EgB6vdFq5ZvYLBW1stJGUwPuXD/iPxPYRztt3Cj7pXF04RRax7iEF6iwVWgsHotz58cDSeUKOIkzakXSvMeVETwNanEnAQgxTCO830AHjiYQ6pFxKQQMLhSR8+Gq9NaKDbiXgaf6sMpRKTDQCrH+TgrEnA+d8C2PNxEeYKJa/1HRy/UxKAW6ba8qfHb5pQ00zXPeOWxQCZHQJaFjOYvRKoGcujbjvXDHEznbGqY5VpEp6Oc9K65a0A770m4MxPAbx9aMEr1GGo0U7kMw1dYQOhGrudJVVmKku4U4fxUthCmpCYHu5k54oQEzmNDbvl0oLnjdyxXl2ijf7/X7fTv29b1lvolvvfAAAAAElFTkSuQmCC"); } .singleunchecked{ background-image: url("data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABYAAAAXCAYAAAF4748IAAAAAXNSR0IArs4c6QAAAERlWElmTU0AKgAAAAgAAYdpAAQAAAABAAAAGgAAAAAAA6ABAAMAAAABAAEAAKACAAQAAAABAAAAFqADAAQAAAABAAAAFwAAAAAhQRrqAAACFElEQVRIDbVUPUhCURT2vafxHGoLqikahZBQKKKptS1QEP9rCmlrj5ocanJoEvWpCA5trc0NSVTQGE1RjTWo+dd3rt7He88bz0d24XrPOd93v3vvOefpcmEUCoUFWl2lUinLDOFPpVJZNQHlcvlU5pF+v7/F7Hq9Ps+D+qpp2qvujAxsX2QmwBAHcYUPbrMVrE09AGZGd2DAfzD6Njbo+0IKgDwBeKLPRAAQ4iAHiITYO/fZinvvmQICB5xruvJYJgRcF2VHHgwGmggUxA5YDOoZYQFGO4CzhElWBeoBt9u9IknSVywWezTiY2TqBFxtttvtPqfT6TcjWbcpRdZ8IpbH1KvNyPxO+k6DQW8BPiw6y58BFJkgD0tMzSkiWGMQzVITX1gBkY/sJIg88SDysDI2W1ilnTxQTiaT23apw6Gq6WBssC2Ko3KPkek4lH0ODzrCTGB+I3SL1LG+h78EPwh/BmtJluVzNNwnbNMwCaOYx/iDSYGxi3ffmZi/OEjmGqBLHFCMx+MnnMaEq9VqoNfrXXk8no1IJPLCQSdrrVZb7nQ6N4qi7ESj0YaE5K5DQFNV1RcOh3tOxKxcNL7SarWeEGcdl0PeUn8VpUNIg7Rg5qg7/V6vt4F1KmOk5Sfh+2azGZiKKkTa7XaQNEn4EK1TpPz8VZw0kIoC0ySxf+kK4y2n3sdGcbIn/fKQQg3zTPTl/QCbiSIVV84yRQAAAABJRU5ErkJggg=="); } .checked{ background-image: url("data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAB4AAAAeCAYAAAFMN540AAAAAXNSR0IArs4c6QAAAERlWElmTU0AKgAAAAgAAYdpAAQAAAABAAAAGgAAAAAAA6ABAAMAAAABAAEAAKACAAQAAAABAAAAHqADAAQAAAABAAAAHgAAAADKQTcFAAACVElEQVRIDWP0KPv5nwEJMCGxwUywwJY2VoaFFaxgAUZ0LRgC2M1ANhhDBYYZyKpBbAwdIMFlNRAnYSjY1AqRiGr5DZIDA4JW4FWA1X6Y0aRJdqSxwDRCvJXsxQwWmJDNwlAx6w+q5Nxtfxnq4pgZCqYiJEAqyHctXp1wy3Ew8HoVhx64MNGaW5JYGJZUIyIXZAIi0ODmoTK6M1gYJIUZGWJaEZEOU4GhOc6NmSHMkYnh/vP/DNwcjAxJXZiaYJoHLsAGzmaiowoWSMj0INfMCkwN2zvZGNjQUgVBZ7MDU+SmVjaG9L7fDL9QsyNqASUmiBwcDAycbAwMG1rYGFK6fzE8eolS4IIVoti8sIKNwVYPIsTFwcCwrpmNIbHzF8PTN6iGwngovvAs/wX222TOPwy5QSwMce2/GF5/gCnFpFFsBkmDDABpTCCgEaR2JCZPivwMCjRyAUZMkWsQqfpGLSY1xDDUswIr+JpYFgYzDUYMOWQBlKyMLEEqG1S0NSSwMBiqMjF8+PKfYclu/CZQbDEHsIRrSmRh0FViYnj3+T9DWu8vhsev8FsKksVpsZ81E0OqNzNDx7I/DEevYBaZXOwMDC3JLAya8kzAAu4/sAL/xfD8LWELYSpwWrzp6D8GIV5GYHyxMvz995+he8VfhoMX/zHwcDIwtKawMKjJMDG8fPefIb7jF8Or9zDjiKeJKkCiXZgYYlxZGP7//8/AyMjI8OzNf4byWb8Z3nwk3iJ0lURZDNNUGs7MsObQX2D7CCZCPk2SxeRbg6lztOTCDBMaiQAAd5umrrmKwxQAAAAASUVORK5CYII="); } .unchecked{ background-image: url("data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABYAAAAWCAYAAAGzs1ytAAAAAXNSR0IArs4c6QAAAERlWElmTU0AKgAAAAgAAYdpAAQAAAABAAAAGgAAAAAAA6ABAAMAAAABAAEAAKACAAQAAAABAAAAFqADAAQAAAABAAAAFgAAAAAcITNaAAAAaUlEQVQ4EWNcuHDhfwYYQOYwwQRBNCOyDLIEGhuXMhTDkPXglCDWRmTDqMjG5RFsVuD0wyBWTJvgBYXaUAyNYe9mBlLSM7Zki02M5NjGZgguMZKiBJch2MRHDYaHymhQ0D4oaFPQAt0NAFtBH+4zl50uAAAAAElFTkSuQmCC"); }
调用页面代码
index.wxml
<!-- 出库类型下拉框 --> <select id="select" options="{{options}}" topsHeight="{{topsHeight}}" opacity="{{opacity}}" IsSingle="{{IsSingle}}" bind:OnSelectFinish="SelectFinish"></select>
json文件需要引用组件
{ "usingComponents": { "select":"../../../../components/select/index" } }
js 文件
const app = getApp(); Page({ /** * 页面的初始数据 */ data: { options: [], //数据集 topsHeight: "30%", //高度 opacity: "0.5", //透明度 IsSingle: true //是否单选 }, /** * 生命周期函数--监听页面加载 */ onl oad: function (options) { //初始化出库类型 this.initExitType(); }, /** * 初始化出库类型 */ initExitType() { /* 这里是系统封装的函数,下面需要换成自己的访问代码*/ var that = this; HTTP.GetExitTypeList().then((res) => { if (res.ErrorCode === 0) { var newArray = []; res.Data.forEach(item => { newArray.push({ "Text": item.Text, "Value": item.Value }); }); that.setData({ options: res.Data }); } }) }, /** * 下拉框选择完成事件 */ SelectFinish: function (even) { console.log(even.detail) }, /** * 显示出库类型下拉框 */ selectStockOutType: function () { this.selectComponent("#select").showPopup(); } })