商城中商品购买中多规格的选择

实现效果:

1.所有规格可以联动

2.库存不足置灰不可选

3.再次点击可以取消选择

<!DOCTYPE html>
<html lang="zh">
	<head>
		<meta charset="UTF-8">
		<meta http-equiv="X-UA-Compatible" content="IE=edge">
		<meta name="viewport" content="width=device-width, initial-scale=1.0">
		<title>规格选择</title>
		<script src="https://cdn.bootcdn.net/ajax/libs/vue/2.6.10/vue.min.js"></script>
		<style>
			html,
			body {
				padding: 0;
				margin: 0;
			}

			#app {
				font-size: 16px;
				width: 100%;
				height: 100%;
				margin: auto;
				padding: 20px;
				box-sizing: border-box;
			}

			.productBox {
				display: block;
				margin: 0 auto;
			}

			.productContent {
				margin-bottom: 50px;
			}

			.productDelcom {
				color: #323232;
				border-bottom: 1px solid #EEEEEE;
				padding-bottom: 30px;
			}

			.productFooter {
				margin-top: 10px;
			}

			.productFooter .specItem {
				border: 1px solid #606060;
				border-radius: 5px;
				color: #606060;
				text-align: center;
				padding: 4px 12px;
				margin-right: 20px;
				cursor: pointer;
				display: inline-block;
			}

			.productFooter .specItem.productActive {
				background-color: #1A1A29;
				color: #fff;
				border: 1px solid #1A1A29;
			}

			.productFooter .specItem.noneActive {
				background-color: #ccc;
				opacity: 0.4;
				color: #000;
				pointer-events: none;
			}

			.buyBtn {
				background-color: #1A1A29;
				color: #fff;
				text-align: center;
				height: 44px;
				display: flex;
				align-items: center;
				justify-content: center;
				width: 90%;
				margin: 0 auto;
				border-radius: 8px;
			}

			.price {
				height: 30px;
				line-height: 30px;
				margin-top: 10px;
			}
		</style>
		</style>
	</head>
	<body>
		<div id="app">
			<div class="productBox">
				<div class="productContent">
					<div class="productDelcom" v-for="(ProductItem,n) in simulatedData.specifications">
						<p>{{ProductItem.name}}</p>
						<div class="productFooter">
							<div class="specItem" v-for="(item,index) in ProductItem.item"
								@click="specificationBtn(item.name,n,$event,index)"
								:class="[item.isShow?'':'noneActive',subIndex[n] == index?'productActive':'']">
								{{item.name}}
							</div>
						</div>
					</div>
					<p class="price"> ¥ {{price}}</p>
				</div>
				<div class="buyBtn">立即购买</div>
			</div>
		</div>
		<script>
			var app = new Vue({
				el: '#app',
				data() {
					return {
						simulatedData: { //模拟后台返回的数据 多规格
							"difference": [{
									"id": "19",
									"price": "200.00",
									"stock": "19", // 库存
									"difference": "100,白色,AA" // 规格
								},
								{
									"id": "20",
									"price": "100.00",
									"stock": "29",
									"difference": "200,白色,AA"
								},
								{
									"id": "21",
									"price": "300.00",
									"stock": "10",
									"difference": "100,黑色,AA"
								},
								{
									"id": "22",
									"price": "900.00",
									"stock": "0",
									"difference": "200,黑色,AA"
								},
								{
									"id": "23",
									"price": "600.00",
									"stock": "48",
									"difference": "100,绿色,AA"
								},
								{
									"id": "24",
									"price": "500.00",
									"stock": "40",
									"difference": "200,绿色,AA"
								},
								{
									"id": "25",
									"price": "90.00",
									"stock": "0",
									"difference": "100,蓝色,AA"
								},
								{
									"id": "26",
									"price": "40.00",
									"stock": "20",
									"difference": "200,蓝色,AAA"
								}
							],
							"specifications": [//这里是要被渲染字段
								{ 
									"name": "尺寸",
									"item": [{
											"name": "100",
										},
										{
											"name": "200",
										}
									]
								},
								{
									"name": "颜色",
									"item": [{
											"name": "白色",
										},
										{
											"name": "蓝色",
										},
										{
											"name": "黑色",
										},
										{
											"name": "绿色",
										}
									]
								},
								{
									"name": "尺寸",
									"item": [{
										"name": "AA",
									}, {
										"name": "AAA",
									}]
								},
							]
						},
						selectArr: [], //存放被选中的值
						shopItemInfo: {}, //存放要和选中的值进行匹配的数据
						subIndex: [], //是否选中 因为不确定是多规格还是单规格,所以这里定义数组来判断
						price: 0 //选中规格的价钱
					}
				},
				mounted() {
					this.checkItem()
				},
				methods: {
					specificationBtn: function(item, n, event, index) {
						if (this.selectArr[n] != item) {
							this.selectArr[n] = item;
							this.subIndex[n] = index;
						} else {
							this.selectArr[n] = "";
							this.subIndex[n] = -1; //去掉选中的颜色
						}
						this.checkItem();
					},
					checkItem: function() {
						var option = this.simulatedData.specifications;
						console.log(option)
						var result = []; //定义数组储存被选中的值
						for (var i in option) {
							result[i] = this.selectArr[i] ? this.selectArr[i] : '';
						}
						console.log(result)
						for (var i in option) {
							var last = result[i]; //把选中的值存放到字符串last去
							for (var k in option[i].item) {
								console.log(result[i])
								console.log(option[i].item[k].name)
								result[i] = option[i].item[k].name; //赋值,存在直接覆盖,不存在往里面添加name值
								option[i].item[k].isShow = this.isMay(result); //在数据里面添加字段isShow来判断是否可以选择
							}
							result[i] = last; //还原,目的是记录点下去那个值,避免下一次执行循环时被覆盖
						}

						if (this.shopItemInfo[result]) {
							let str = this.shopItemInfo[result].difference.split(',')
							this.price = str.length == 3 ? this.shopItemInfo[result].price : 0
						} else {
							this.price = 0
						}
						self.$forceUpdate(); // 强制更新
					},
					isMay: function(result) {
						for (var i in result) {
							if (result[i] == '') {
								return true; //如果数组里有为空的值,那直接返回true
							}
						}
						console.log(result)
						console.log(this.shopItemInfo[result])
						return !this.shopItemInfo[result] || this.shopItemInfo[result].stock == 0 ? false :
							true; //匹配选中的数据的库存,若不为空返回true
					}
				},
				created: function() {
					console.log(this.simulatedData.difference)
					for (var i in this.simulatedData.difference) {
						this.shopItemInfo[this.simulatedData.difference[i].difference] = this.simulatedData
							.difference[i];
					}
					//[100,白色,AA: {}, 100,白色,AA: {}]
					console.log(this.shopItemInfo)
					this.checkItem();
				}

			})
		</script>
	</body>
</html>

  

posted @ 2022-12-02 18:01  月下云生  阅读(126)  评论(0)    收藏  举报