uniapp 学习笔记二十五 购物车弹窗页面下拉选择交互 商品规格数据渲染及数据动态交互
购物车弹窗页面下拉选择交互
商品规格数据渲染及数据动态交互
cart.vue
<template>
<view>
<view class="flex padding" v-for="(item,index) in cartList">
<view class="flex align-center">
<text @click="handleCheck(index)" :class="['iconfont','icon-youxiajiaogouxuan','margin-right',{'yellow':item.isCheck}]"></text>
<image class="poster margin-right" :src="item.img" mode=""></image>
</view>
<view class="flex justify-between info">
<view class="">
{{item.name}}
<view class="margin-tb-xs"> {{item.french}} </view>
Y{{item.price}}
</view>
<view class="flex flex-direction align-end">
<view @click="handleEdit(index)" class="edit margin-bottom-xs">
<text class="iconfont icon-bianjishuru"></text>
</view>
{{cartList[cartIdx].list[cartList[cartIdx].idx].spec}}
X 1
</view>
</view>
</view>
<!-- 弹窗 -->
<u-overlay :show="show" @click="show=false">
<view class="bg-fff margin cover-cont" @click.stop>
<view class="padding">
<view class="flex justify-between info">
<image class="poster margin-right" src="" mode=""></image>
<view class="">
{{cartList[cartIdx].name}}
<view class="margin-tb-xs"> {{cartList[cartIdx].french}} </view>
Y{{cartList[cartIdx].list[cartList[cartIdx].idx].price}}
</view>
</view>
<view class="flex justify-between padding-tb u-border-bottom">
<view class="">
规格选择
</view>
<view class="drop">
<view @click="dropShow=true">
{{cartList[cartIdx].list[cartList[cartIdx].idx].spec}} - {{cartList[cartIdx].list[cartList[cartIdx].idx].edible}}
<text class="iconfont icon-xiangxiazhankai"></text>
</view>
<view v-if="dropShow" class="drop-list bg-fff">
<view
v-for="(item,index) in cartList[cartIdx].list"
class="padding-sm"
:key="index"
@click="handleDropList(index)"
>
{{item.spec}} - {{item.edible}}
</view>
</view>
</view>
</view>
<view class="flex justify-between align-center padding-tb u-border-bottom">
<view class="">
数量选择
</view>
<u-number-box button-size="36"></u-number-box>
</view>
</view>
<view class="flex margin-top">
<button type="default" class="cu-btn lg bg-brown">取消</button>
<button type="default" class="cu-btn lg bg-yellow">确认</button>
</view>
</view>
</u-overlay>
<view class="fixed bg-fff flex">
<view class="flex flex-sub padding align-center">
<text
@click="handleAllCheck(allInfo.allCheck)"
:class="['iconfont', 'icon-youxiajiaogouxuan', 'margin-right-xs',{'yellow':allInfo.allCheck}]"></text>
全选
<view class="margin-left">
共计:189
</view>
</view>
<view class="bg-yellow padding text-center color-fff">
立即结算
</view>
</view>
</view>
</template>
<script>
import {mapState,mapMutations,mapGetters} from 'vuex'
export default {
data() {
return {
show:false,
dropShow:false,
cartIdx:0
}
},
computed: {
...mapState({
cartList:state=>state.cart.cartList
}),
...mapGetters({
allInfo:'cart/allInfo'
}),
checkedCartInfo(){ // 过滤下拉选中的商品对象
let {cartIdx,cartList} = this
return cartList[cartIdx].list[cartList[cartIdx].idx]
}
},
methods:{
...mapMutations({
handleCheck:'cart/cartCheckMut',
handleAllCheck:'cart/cartAllCheckMut'
}),
handleEdit(idx){
// 弹窗控制
this.cartIdx = idx;
this.show=true;
},
handleDropList(dropIdx){ //子商品下拉列表
this.dropShow = false;
let {cartIdx} = this;
this.$store.commit('cart/cartListCheckMut',{cartIdx,dropIdx});
}
}
}
</script>
<style lang="scss">
page{
padding-bottom: 100upx;
}
.poster{
width: 180upx;
height: 180upx;
background-color: #d8d8d8;
}
.info{
width: 60%;
.edit{
width: 80upx;
height: 80upx;
text-align: center;
line-height: 80upx;
background-color: #e6e6e6;
border-radius: 50%;
}
}
.icon-youxiajiaogouxuan{
width: 50upx;
height: 50upx;
text-align: center;
line-height: 50upx;
background-color: #e6e6e6;
border-radius: 20%;
}
.fixed {
position: fixed;
bottom: 0;
left: 0;
width: 100%;
box-shadow: 0 0 10upx 2upx rgba(0, 0, 0, 0.2);
}
.yellow{
background-color: yellow;
}
.cu-btn.lg{
width: 50%;
}
.cover-cont{
position: absolute;
top: 50%;
left: 0;
width: 690upx;
transform: translateY(-50%);
border-radius: 10upx;
}
.drop{
position: relative;
.drop-list{
width:300upx;
position: absolute;
top: 60upx;
right: 0;
box-shadow: 0 0 10upx 2upx rgba(0, 0, 0, 0.2);
z-index: 10;
view:hover{
background-color: #e6e6e6;
}
}
}
</style>
cart.js
export default {
namespaced:true,
state(){
return {
cartList:[{
id:"10090",
twoId:10089,
name:"拿破仑草莓恋爱",
french:"Napoleon aux fraises",
price:"208.00",
isCheck:false,
img:"/static/logo.png",
list:[
{id:10090,sku:"n0201",ahead:'提前5小时预定',edible:"2-3人食用",spec:"1磅",price:"218.00"},
{id:10091,sku:"n0202",ahead:'提前5小时预定',edible:"4-7人食用",spec:"2磅",price:"318.00"},
{id:10092,sku:"n0203",ahead:'提前5小时预定',edible:"8-12人食用",spec:"3磅",price:"458.00"},
{id:10093,sku:"n0204",ahead:'提前5小时预定',edible:"12-20人食用",spec:"5磅",price:"750.00"}
],
num:1,//商品数量
idx:0 //标记选中的子商品信息
},{
id:"10090",
twoId:10089,
name:"拿破仑草莓",
french:"Napoleon aux fraises",
price:"218.00",
tid:11,
tname:'限定',
isCheck:false,
img:"/static/logo.png",
list:[
{id:10090,sku:"n0201",ahead:'提前5小时预定',edible:"2-3人食用",spec:"1磅",price:"218.00"},
{id:10091,sku:"n0202",ahead:'提前5小时预定',edible:"4-7人食用",spec:"2磅",price:"318.00"},
{id:10092,sku:"n0203",ahead:'提前5小时预定',edible:"8-12人食用",spec:"3磅",price:"458.00"},
{id:10093,sku:"n0204",ahead:'提前5小时预定',edible:"12-20人食用",spec:"5磅",price:"750.00"}
],
num:1, //商品数量
idx:0 //标记选中的子商品信息
}
]
}
},
getters:{
allInfo(state){
let allCheck = true
state.cartList.forEach(item=>{
if(!item.isCheck){
allCheck = false
}
})
return {allCheck}
}
},
mutations:{
cartCheckMut(state,idx){ // 单选
state.cartList[idx].isCheck = !state.cartList[idx].isCheck
},
cartAllCheckMut(state,bool){ // 全选 bool 是原本的全选状态
state.cartList.forEach(item=>{
item.isCheck = !bool
})
},
cartListCheckMut(state,{cartIdx,dropIdx}){ // 子商品下拉处理
state.cartList[cartIdx].idx = dropIdx
}
}
}