小程序封装弹窗组件(使用uview框架中的u-popup弹窗组件)
效果展示
文章来源地址https://www.toymoban.com/news/detail-669311.html
代码结构
结构分析
最外层页面index.vue-可点击"选择优惠券",进入弹窗组件selector.vue进行内容选择,弹窗组件中包含滚动列表,每个列表项为一个coupon.vue组件
核心代码
index.vue
template:
<!-- 优惠券区域 -->
<view class="rescue-coupon">
<view class="coupon-select">
<view class="title">
选择优惠券
</view>
<view class="piker" @click="open">
选择优惠券
<selector ref="saleArea" @getApplyCoupon="getApplyCoupon" /> // 设置自定义事件-方便子组件传递选择的优惠券过来
</view>
</view>
<view class="apply-coupon">
<coupon :item="applyCoupon" :imgShow="false" />
</view>
</view>
js:
<script>
import http from "@/js/api.js" // 请求发送组件
import selector from './selector.vue' // 弹窗组件
import coupon from './coupon.vue' // 列表项组件
import { cloneDeep } from "lodash" // 深拷贝
export default {
components: {
selector,
coupon
},
data() {
return {
// 使用的优惠券
applyCoupon:{},
// 优惠券列表
couponList:[],
show:false
}
},
methods: {
// 获取优惠券列表数据-可用优惠券
getCouponList() {
console.log('调用了优惠券列表查询方法')
let opt = {
url: url, // 接口地址
data: data, // 请求参数
method: 'GET'
}
http(opt).then(res => {
console.log('优惠券列表响应数据',res)
this.couponList = res.list
if(this.couponList.length >= 1) { // 可用优惠券数量不小于1时 为每个优惠券对象动态添加check属性-为后续勾选提供便利
for(let i = 0; i < this.couponList.length; i ++) {
this.$set(this.couponList,'check',false) // 注意此处需要实现响应式-使用$set API实现(vue)
}
this.couponList[0].check = true // 默认第一张优惠券状态为选中
}
}).catch(error => {
uni.showToast({title: error.message || '网络超时', icon: 'none'});
});
},
// 获取子组件传递过来的确定使用的优惠券
getApplyCoupon(obj) {
console.log('接收到的优惠券:',obj)
this.applyCoupon = obj
this.params.couponId = obj.id
},
// 展开优惠券选择弹窗
open(){
this.$refs.saleArea.show = true
this.$refs.saleArea.couponList = cloneDeep(this.couponList)
if(this.applyCoupon.id) { // 存在已选择优惠券
this.$refs.saleArea.filterCoupons(this.applyCoupon.id)
}else { // 暂无已选优惠券
this.$refs.saleArea.filterCoupons(999)
}
}
}
</script>
selector.vue
<template>
<u-popup v-model="show" mode="bottom" border-radius="16"> // uview框架的弹出层组件
<view class="box">
<!-- 关闭 -->
<view class="close" @click="close">
<image src="../../../static/coupon/couponClose.png" mode=""></image>
</view>
<!-- 标题 -->
<view class="title">
选择优惠券
</view>
<!-- 优惠券列表 -->
<scroll-view class="list" scroll-y="true" enhanced :show-scrollbar="false" v-if="couponList.length !== 0">
<view v-for="item,i in couponList" :key="i" @click="handlerClick(item)">
<coupon :item="item" />
</view>
</scroll-view>
<emptyList title="暂无可用优惠券" v-else></emptyList>
<!-- 底部按钮 -->
<view class="bottom" @click="apply">
立即使用
</view>
</view>
</u-popup>
</template>
<script>
import emptyList from './emptyList.vue'
import coupon from './coupon.vue'
export default {
components:{
coupon,
emptyList
},
data() {
return {
couponList:[],
applyCoupon:{}, // 确定使用的优惠券
show: false
}
},
methods: {
// 已选优惠券情况下再次进入优惠券选择页面-设置已选优惠券状态为已勾选状态
filterCoupons(id) {
if(id === 999) { // 当前不存在已选优惠券-则默认第一张优惠券为勾选状态
this.applyCoupon = this.couponList[0]
}else { // 当前存在已选优惠券-则筛选出该优惠券并将其设为勾选状态
this.couponList.forEach(item=>{
item.check = false
})
for(let i = 0; i < this.couponList.length; i++) {
if(this.couponList[i].id === id) {
this.couponList[i].check = true
}
}
}
},
// 勾选
handlerClick(data){
console.log('选择的优惠券',data)
this.applyCoupon = data
this.couponList.forEach(item=>{
item.check = false
})
for(let i = 0; i < this.couponList.length; i++) {
if(this.couponList[i].id === data.id) {
this.couponList[i].check = true
}
}
},
// 立即使用
apply() {
if(this.applyCoupon) {
this.show = false
this.$emit('getApplyCoupon',this.applyCoupon) // 将确定使用的优惠券传递给父组件
}else {
this.show = false
}
},
// 关闭弹窗
close() {
this.show = false
}
}
}
</script>
<style lang="scss" scoped>
.box {
width: 750rpx;
max-height: 1361rpx;
background: #FFFFFF;
opacity: 1;
padding: 32rpx;
.close {
text-align: right;
image {
width: 48rpx;
height: 48rpx;
margin-bottom: -10rpx;
}
}
.title {
font-size: 32rpx;
font-family: PingFang SC-Semibold, PingFang SC;
font-weight: 600;
color: #1A1D24;
margin-bottom: 26rpx;
margin-left: 12rpx;
}
.list {
max-height: 1000rpx;
}
.bottom {
width: 686rpx;
height: 72rpx;
background: #2972FF;
border-radius: 16rpx 16rpx 16rpx 16rpx;
opacity: 1;
margin-top: 40rpx;
font-size: 28rpx;
font-family: PingFang SC-Medium, PingFang SC;
font-weight: 500;
color: #FFFFFF;
text-align: center;
line-height: 72rpx;
}
}
</style>
coupon.vue
<template>
<view>
<!-- 金额优惠券 -->
<view class="moneyItem" v-if="item.couponType === 1">
<view class="left">
<span><span class="unity">¥</span>{{ item.couponAmt }}</span>
<span>可用金额¥{{ item.usedAmt }}</span>
</view>
<view class="right">
<span :class="{ one:!imgShow }">可用车辆:{{ changeFormat(item.customerType) }}</span>
<span>
<image v-show="imgShow" class="two" :src="item.check ? selectUrl : unSelectUrl" mode=""></image>
</span>
<span class="three">{{ item.effectDate }}至{{ item.expireDate }}</span>
</view>
</view>
<!-- 服务优惠券 -->
<view class="serviceItem" v-if="item.couponType === 2">
<view>
<view class="left">
<span>服务券</span>
</view>
<view class="right">
<span :class="{ one:!imgShow }">可用车辆:{{ changeFormat(item.customerType) }}</span>
<span>
<span>{{ item.contentTitle }}</span>
<image v-show="imgShow" class="two" :src="item.check === true ? selectUrl : unSelectUrl" mode=""></image>
</span>
<span class="three">{{item.effectDate}}至{{item.expireDate}}</span>
</view>
</view>
<view @click="change">
<span :style="[{overflow:(index === 1 ? 'hidden' : 'auto')},{whiteSpace:(index===1?'nowrap':'normal')},{textOverflow:(index===1?'ellipsis':'clip')}]">详情:{{item.couponDesc}}</span>
<image :src="detailUrl" mode=""></image>
</view>
</view>
</view>
</template>
<script>
export default {
name:'coupon',
props:{
item:{
type:Object,
default:{}
},
imgShow: {
type:Boolean,
default:true
}
},
filters: {
customerFilter(val) {
if(val === 'PERSON') {
return this.item.truckVin
}else {
return this.item.fleetName
}
}
},
data() {
return {
index:1,
detailUrl:'../../../static/coupon/bottom.png',
onUrl:'../../../static/coupon/top.png',
offUrl:'../../../static/coupon/bottom.png',
// 勾选
chooseUrl:'../../../static/coupon/couponSelect.png',
selectUrl:'../../../static/coupon/couponSelect.png',
unSelectUrl:'../../../static/coupon/couponUnselect.png',
}
},
watch: {
detailUrl(val) {
if(val === this.offUrl) {
this.index = 1
}else {
this.index = 2
}
}
},
methods: {
// 详情展开/关闭
change() {
if(this.detailUrl === this.offUrl) {
this.detailUrl = this.onUrl
}else {
this.detailUrl = this.offUrl
}
},
changeFormat(val) {
if(val === 'PERSON') {
return this.item.truckVin
}else {
return this.item.fleetName
}
}
}
}
</script>
<style scoped lang="scss">
.moneyItem {
display: flex;
height: 202rpx;
background: #F4F8FF;
opacity: 1;
background-image: url('../../../static/coupon/couponBac.png');
background-size: 100%;
margin-bottom: 20rpx;
padding-top: 15rpx;
padding-left: 15rpx;
.left {
display: flex;
justify-content: center;
align-items: center;
flex-direction: column;
width: 186rpx;
height: 190rpx;
&>span {
&:first-child {
font-size: 40rpx;
font-family: PingFang SC-Medium, PingFang SC;
font-weight: 500;
color: #FFFFFF;
margin-bottom: 10rpx;
.unity {
font-size: 22rpx;
}
}
&:last-child {
font-size: 24rpx;
font-family: PingFang SC-Regular, PingFang SC;
font-weight: 400;
color: #FFFFFF;
}
}
}
.right {
flex: 1;
display: flex;
flex-direction: column;
justify-content: center;
padding-left: 30rpx;
.one {
margin-bottom: 48rpx;
}
&>span {
&:first-child {
font-size: 32rpx;
font-family: PingFang SC-Medium, PingFang SC;
font-weight: 500;
color: #1A1D24;
}
&:nth-child(2) {
text-align: right;
padding: 0;
image {
width: 48rpx;
height: 48rpx;
margin-right: 32rpx;
margin-bottom: -10rpx;
}
}
&:last-child {
font-size: 28rpx;
font-family: PingFang SC-Regular, PingFang SC;
font-weight: 400;
color: #76777C;
}
}
}
}
.serviceItem {
background: #F4F8FF;
margin-bottom: 20rpx;
&>view {
&:first-child {
opacity: 1;
height: 202rpx;
padding-top: 15rpx;
padding-left: 15rpx;
display: flex;
background-image: url('../../../static/coupon/couponBac.png');
background-size: 100%;
.left {
display: flex;
justify-content: center;
align-items: center;
flex-direction: column;
width: 186rpx;
height: 190rpx;
span {
font-size: 48rpx;
font-family: PingFang SC-Medium, PingFang SC;
font-weight: 500;
color: #FFFFFF;
}
}
.right {
flex: 1;
display: flex;
flex-direction: column;
justify-content: center;
padding-left: 30rpx;
&>span {
&:first-child {
font-size: 32rpx;
font-family: PingFang SC-Medium, PingFang SC;
font-weight: 500;
color: #1A1D24;
}
&:nth-child(2) {
display: flex;
justify-content: space-between;
padding: 0;
font-size: 28rpx;
font-family: PingFang SC-Regular, PingFang SC;
font-weight: 400;
color: #46484E;
margin-top: 8rpx;
image {
width: 48rpx;
height: 48rpx;
margin-right: 32rpx;
margin-bottom: -10rpx;
}
}
&:last-child {
margin-top: 30rpx;
font-size: 28rpx;
font-family: PingFang SC-Regular, PingFang SC;
font-weight: 400;
color: #76777C;
}
}
}
}
&:last-child {
width: 100%;
padding: 15rpx 22rpx;
font-family: PingFang SC-Regular, PingFang SC;
font-weight: 400;
color: #76777C;
background: #FAFAFA;
border-radius: 0 0 16rpx 16rpx;
opacity: 1;
display: flex;
justify-content: space-between;
span {
flex: 1;
}
image {
margin-left: 16rpx;
width: 32rpx;
height: 32rpx;
}
}
}
}
</style>
文章来源:https://www.toymoban.com/news/detail-669311.html
到了这里,关于小程序使用uview中的u-popup弹窗组件的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!