uni-app类似淘宝选择商品多规格(库存判断)

Posted GHUIJS

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了uni-app类似淘宝选择商品多规格(库存判断)相关的知识,希望对你有一定的参考价值。

 1.组件效果展示


瞎封装组件系列:

VUE简单提示框

VUE树形图(递归实现)

VUE多店铺购物车

 2.使用方法

引入组件:

import goodsSpec from '@/components/goodsSpec.vue'

在<template>合适的区域使用

<button type="default" @click="isShow = true">选择规格</button>
<goods-spec v-if="goodsDate" :isShow="isShow" :goodsData="goodsDate" @hiddenModal='hiddenModal'></goods-spec>

组件规定需要从父组件传商品规格信息的JSON,和一个布尔值,控制规格选择弹出框显示状态。

商品规格信息JSON必须符合组件规定标准,例子中的数据模拟接口地址是:

https://www.fastmock.site/mock/961b619357977ecee63001f0f5140734/yghh/goodsSkuTree

例子源码:

<template>
	<view>
<button type="default" @click="isShow = true">选择规格</button>
<goods-spec v-if="goodsDate" :isShow="isShow" :goodsData="goodsDate" @hiddenModal='hiddenModal'></goods-spec>
	</view>
</template>

<script>
	import goodsSpec from '@/components/goodsSpec.vue'
	export default {
		data() {
			return {
				list:[],
				goodsDate:null,
				isShow:false
			}
		},
		created() {
			// https://www.fastmock.site/mock/961b619357977ecee63001f0f5140734/yghh/goodsSkuTree
			this.$request.get('/goodsSkuTree').then(res => {
				this.goodsDate = res.data;
			})
		},
		components:{
			goodsSpec
		},
		methods: {
			hiddenModal(){
				this.isShow = false
			}
		}
	}
</script>

<style>

</style>

3.代码实现

实现原理:

点击规格按钮时,把所选规格装到一个数组中,最后把组合的规格代入商品数量的json中查找。

<template>
	<transition name="fade">
		<view class="spec-shade" v-if="isShow" @click.self="hiddenModal">
			<view class="spec-cont">
				<view class="goods-choose-show flex-star">
					<img src="../static/img/mba_banner3.jpg">
					<view class="goods-choose-show-right" v-if="currentItem">
						<p>¥{{currentItem.price || 0}}</p>
						<view>库存{{currentItem.stock || 0}}件</view>
						<view>{{specShowString}}</view>
					</view>
					<i class="iconfont icon-cuowu" @click.stop='hiddenModal'></i>
				</view>
				<view class="spec-linebox">
					<view class="spec-item" v-for="(skuItem,skuIndex) in skuInfo">
						<p>{{skuItem.name}}</p>
						<view class="item-cont flex-star">
							<span v-for="(item,index) in skuItem.items"
								:class="[item.isShow ? '' : 'noProduct',subIndex[skuIndex] == index ? 'act' : '']"
								@click="item.isShow ? specificationBtn(item.name,skuIndex,index) : $msg({
									msg: '不可点击',
									type: 'warning',
									time: 1500
								})">{{item.name}}</span>
						</view>
					</view>
				</view>
			</view>
		</view>
	</transition>	
</template>

<script>
	export default {
		name: "goodsSpec",
		data() {
			return {
				skuInfo: [],
				selectArr: [], //当前已选规格数组
				specShowString: '选择规格', //已选规格字符串展示
				currentItem: {
					price: 0,
					stock: 0
				}, //规格选完后的对象
				subIndex: [] //规格选中样式
			};
		},
		props: {
			goodsData: {
				type: Object,
				required: true
			},
			isShow: false
		},
		created() {
			this.skuInfo = this.goodsData.SKUInfo;
			this.skuInfo.forEach(item => {
				item.items.forEach(specItem => {
					specItem.isShow = true;
				})
			})
		},
		methods: {
			hiddenModal(){
				this.$emit('hiddenModal',false)
			},
			/**
			 * @param {String} specName 当前点击规格按钮的值(黑色,35)
			 * @param {Number} specIndex 选择的规格下标(例子中颜色是0,尺码是1)
			 * @param {Number} specItemIndex 选择规格值下标(例子中35下标是0)
			 */
			specificationBtn(specName, specIndex, specItemIndex) {
				if (this.selectArr[specIndex] != specName) {//判断所选规格数组中是否包含当前点击规格
					this.selectArr[specIndex] = specName;//如果没有则把当前规格添加
					this.subIndex[specIndex] = specItemIndex;//添加选中样式
				} else {
					this.selectArr[specIndex] = '';
					this.subIndex[specIndex] = -1;//去除样式
				}
				this.specShowString = this.spaceRemoveArr(this.selectArr).join(';') || '选择规格';//所选规格页面中展示,数组为空则变为选择规格
				this.inventoryLookup();//当规格选完后,去匹配
				this.clickPitch();//库存判断,实现不可点击
			},
			spaceRemoveArr(arr) {//数组去除空字符串
				let tempArr = []
				arr.forEach(item => {
					if (item) {
						tempArr.push(item)
					}
				})
				return tempArr;
			},
			inventoryLookup() {
				try {
					this.goodsData.priceInfo.forEach((item, index) => {
						if (item.difference == this.specShowString) {
							this.currentItem = item;
							throw new Error();
						} else {
							this.currentItem = {
								SKU: '',
								price: 0,
								stock: 0
							};
						}
					})
				} catch (e) {}
			},
			clickPitch() {
				let result = [];
				for (let i in this.goodsData.SKUInfo) {
					result[i] = this.selectArr[i] ? this.selectArr[i] : '';
				}
				
				//最难理解的大概就是这里了,这里跟着循环里打印结果,多走几遍就大致明白了  假象.jpg
				for (let i in this.goodsData.SKUInfo) {
					let last = result[i];
					console.log(result,'****************')
					for (let k in this.goodsData.SKUInfo[i].items) {
						result[i] = this.goodsData.SKUInfo[i].items[k].name;
						console.log(result,last)
						this.skuInfo[i].items[k].isShow = this.isMay(result)
					}
					result[i] = last;
				}
			},
			isMay(result) {
				for (let i in result) {
					if (result[i] == '') {
						return true;
					}
				}
				for (let i in this.goodsData.priceInfo) {
					if(this.goodsData.priceInfo[i].difference == result.join(";") && this.goodsData.priceInfo[i].stock > 0){
						return true;
					}
				}
			}
		},
		computed: {}
	}
</script>

<style lang="scss" scoped>
	.fade-enter-active, .fade-leave-active {
	  transition: opacity .5s;
	}
	.fade-enter, .fade-leave-to /* .fade-leave-active below version 2.1.8 */ {
	  opacity: 0;
	}
	
	.spec-shade {
		position: fixed;
		left: 0;
		top: 0;
		bottom: 0;
		right: 0;
		background: rgba(0, 0, 0, .1);

		.spec-cont {
			background: white;
			position: absolute;
			bottom: 0;
			left: 0;
			width: 100%;
			padding: 20upx;

			.goods-choose-show {
				margin: -40upx 0 10upx 0;

				img {
					width: 180upx;
					height: 180upx;
					box-shadow: 0 0 10px rgba(0, 0, 0, .2);
					border-radius: 10upx;
					margin-right: 20upx;
					border: 5upx solid #fff;
				}

				.goods-choose-show-right {
					position: relative;

					p {
						color: #FE9E01;
						font-size: 32upx;
						font-weight: bold;
					}

					view {
						color: #666;
						font-size: 26upx;
						margin-top: 5upx;
					}
				}

				i.icon-cuowu {
					position: absolute;
					top: 30upx;
					right: 30upx;
				}
			}

			.spec-item {
				padding: 15upx 0;
				border-bottom: 1px solid #eee;

				p {
					font-weight: bold;
					line-height: 50upx;
				}

				.item-cont {
					padding: 15upx 0;

					span {
						display: inline-block;
						padding: 10upx 18upx;
						border-radius: 8upx;
						color: #666;
						font-size: 36upx;
						background: #F6F4F5;
						margin-right: 15upx;
					}

					span.act {
						background: #FDAB27;
						color: white;
					}

					span.noProduct {
						color: #ccc;
					}
				}
			}


		}
	}
</style>

写的不好,多多指教。

以上是关于uni-app类似淘宝选择商品多规格(库存判断)的主要内容,如果未能解决你的问题,请参考以下文章

SKU商品规格选择

商品规格选择弹窗设计总结

淘宝怎么添加购物车

解决商品超卖问题

多规格的商品选择不同的规格值影响其他规格使之不可选

sku多规格属性组合库存判断 - iOS