后台接口返回的数据结构

在这里插入图片描述

在vue中,使用forEach()来处理成自己想要的数据

data() {
	return {
		show:false,//商品规格弹框
		price:'',//商品默认价格
		stock_num:'',//商品默认总库存
		if_sku:true,//判断该商品是否有规格
		sku:[],//商品规格
		skuPrice:[],//规格对应的价格和库存
		select_id:[],//选中的规格id、组成的数组
		select_id2:[],//选中的规格id、需要提交给后台
		value:'',//商品购买数量
	}
}
mounted(){
	//在这里请求接口获取商品数据,我就不写了,直接写数据的处理逻辑
	this.price = res.data.detail.price;//商品默认价格
	this.stock_num = res.data.detail.amount;//商品默认总库存
	
	// 商品分两种操作,一种无规格直接可以购买,一种有规格,需要判断先选择规格后才能操作
	if(res.data.sku.length == 0){
		//无规格
		this.if_sku = false;
	}else{
		//有规格
		this.if_sku = true;
		res.data.sku.forEach(item=>{ // 这里的item 就是接口返回的 sku,
			let obj = {
				name:'', // 大规格名称:如颜色,尺寸
				list:[], // 具体的大规格下的小规格,如颜色下边有黑色,白色
			}
			obj['name'] = item.standard.name,//大规格名称
			obj['list'] = item.skuValues,//具体某个规格下的所有规格
			obj.list.forEach(val=>{
				this.$set(val,'active',false); // 新增active字段来判断当前选中高亮状态
			})
			this.sku.push(obj); // this.sku 用来循环渲染页面
			
		})
	}
}

我们重组后的数据格式如下

在这里插入图片描述

现在用该数据渲染html,这里只展示规格弹窗页面结构,具体样式就不再写了

<van-popup v-model="show" position="bottom" round>
	<div class="title">
			<img :src="detail.mainPic" alt="">
			<div class="text">
				<div class="price"><b>{{price}}</b></div>
				<span>剩余 {{stock_num}}件</span>
				<span>请选择商品规格</span>
			</div>
		</div>
		<div class="content">
			<div class="item" v-for="(item,index) in sku" :key="index">
				<h2>{{item.name}}</h2>
				<div class="val">
					<!-- sku_id 方法,用来获取点击项,给对应的数据高亮显示,并拿到点击的id -->
					<p @click="sku_id(val.id,index,i)" :class="{active:val.active==true}" v-for="(val,i) in item.list" :key="i">{{val.name}}</p>
				</div>
			</div>
			<div class="num">
				<p>购买数量</p>
				<van-stepper min="1" v-model="value" />
			</div>
			<div class="btn">
				<button @click="addCart">加入购物车</button>
				<button @click="buy">立即购买</button>
			</div>
		</div>
	</van-popup>

具体的sku_id()方法实现

sku_id(id,index,i){
	/*
	 id:当前商品id、
	 index:大规格的索引,具体点击的是颜色,还是尺寸
	 i:小规格的索引,点击的是颜色规格下的黑色,还是白色,
	 这里的index和i、用来控制点击项的高亮展示,同时需要id、push进对应索引的 select_id[]
	*/
	  
	/*
	 this.select_id[index]
	 1.如果此时你点击的是第一项:号码,那么 index == 0,循环this.sku[0].list 
	 如果满足item.id == id 这个条件,就返回item这个数据,把该数据的id、赋值给this.select_id[0]
	 2.如果此时你点击的是第二项:颜色,那么 index == 1,循环this.sku[1].list
	 如果满足item.id == id 这个条件,就返回item这个数据,把该数据的id、赋值给this.select_id[1]
	 3.这样我们就拿到了[10,15] 这样的数据(黑色,43号),用这个数据去跟后台返回的skuPrice做对比,如果值相同,则展示对应的价格和库存
	*/
	this.select_id[index] = this.sku[index].list.filter(item=>{ 
		return item.id == id ;
	})[0].id;

	// 点击的是哪个规格,在点击后的高亮处理
	this.sku[index].list.forEach(item=>{ 
		if(item.id == id ){
			this.sku[index].list[i].active = true;
		}else{
			item.active = false;
		}
	})
	/*
	 如果 select_id的length等于this.sku.length,说明此时规格已全部选择完毕,
	 开始和后台返回的 skuPrice 数据做对比,如果全部相等,则展示对应的价格和库存,
	 matchingArrays 就是当前选中项的价目表,

	*/
	this.matchingArrays = this.findMatchingData(this.select_id, this.skuPrice);
	console.log(this.matchingArrays);

	
},
findMatchingData(input, target) {
	for (const item of target) {
		// 检查是否与输入数组1的sku_ids匹配
		if (JSON.stringify(item.sku) === JSON.stringify(input)) {
			return item; // 返回找到的匹配数据
		}
	}
	return null; // 如果未找到匹配数据,返回null或者其他默认值
},

//写到这里,完整的规格选择已经做完了,下面是加入购物车,跟购买同理,只写下购物车操作

addCart(){
	for(var i=0;i<this.sku.length;i++){
		if(this.select_id[i] == undefined){
			return this.$toast.fail('请选择完整规格')
		}
	}
	if(Number(this.value)>Number(this.stock_num)){
		this.$toast.fail('库存不足')
	}else{
		if(this.if_sku){
			//有规格
			if(this.select_id.length < this.sku.length){
				this.$toast.fail('请选择商品规格')
			}else{
				let data = {
					num:this.value,
					productId:this.detail.id,
					skuIds:this.select_id2,
				}
				getAddCart(data).then(res=>{
					if(res.errCode == 100){
						this.$toast.success('添加购物成功')
						this.show = false;
					}
				})
			}
		}else{
			//无规格
			let data = {
				num:this.value,
				productId:this.detail.id,
				skuIds:[],
			}
			getAddCart(data).then(res=>{
				if(res.errCode == 100){
					this.$toast.success('添加购物成功')
					this.show = false;
				}
			})
		}
	}
},
Logo

前往低代码交流专区

更多推荐