小程序类似淘宝选择规格的轮子

小程序类似淘宝选择规格的轮子


基本实现代码

<template>
	<view class="container">
		<view class="skuBox">
			<view class="color" v-for="(item,index) in skuData" :key="index">
				<view class="type_contnent_box">
					<view class="title">
						{{item.attr_name}}
					</view>
					<view class="color_item_container">
						<view class="color_item" 
						:class="{'active':isActive[index]==index+''+typeIndex}" 
						:data-id="index+''+typeIndex" 
						 v-for="(typeItem,typeIndex) in item.attrs" :key="typeIndex" 
						@tap="clickSku($event,typeIndex,typeItem,index)">
							{{typeItem.attr_name}}
						</view>
					</view>	
				</view>
			</view>
		</view>
	</view>
</template>

<script>
	export default {
		data() {
			return {

				isActive: [],

				skuData: [],
				
				arr: []

			}
		},
		methods: {
			clickSku(e, typeIndex, typeItem, index) {
				console.log('typeitem', e, '规格列表index', index)
				/* 这里是两层数据 */
				// let arr = []
				for (let i = 0, len = this.skuData.length; i < len; i++) {
					/* 每条规格项里的规格子项 */
					for (let j = 0, len = this.skuData[i].attrs.length; j < len; j++) {
						if (e.target.dataset.id == i + '' + j) {
							this.arr[i] = i + '' + j
							this.isActive = this.arr.concat()
						}
					}
				}
				console.log('外层个位内层十位', this.isActive, this.arr)
			},
		},
		onLoad() {
			uni.request({
				url: 'https://www.easy-mock.com/mock/5cb08b01feb0256836781213/selectSkuData',
				data: {},
				header: {},
				success: (res) => {
					console.log(res.data);
					this.skuData = res.data
				},
				fail: (err) => {
					console.log(err)
				}
			});
		}

	}
</script>

<style lang="scss" scoped>
	.skuBox {
		height: 400upx;
		overflow-y: scroll;

		.color {
			height: 200upx;
			border-bottom: 1upx solid rgba($color: #000000, $alpha: .1);

			.title {
				font-size: .8rem;
			}

			.color_item_container {
				height: 100%;
				display: flex;
				flex-wrap: wrap;
				flex-direction: row;
				justify-content: start;
				margin-top: 40upx;

				.color_item {
					margin-right: 35upx;
					margin-bottom: 20upx;
					position: relative;
					width: 120upx;
					text-align: center;
					border: 1upx solid #444444;
					line-height: 1.1rem;
					font-size: .7rem;
					text-align: center;
					border-radius: 10upx;

				}

				.active {
					background: peachpuff;
					border: 1upx solid #E94D68;
				}
			}

		}
	}
</style>



两层循环不好加样式

通过的外层索引的下标给相应的数组赋值,
点击第一层的内存规格就会给数组中的第一个元素赋值,第二层就会给第二个赋值,
通过自定义属性data-id把外层索引和内层索引组合成一个两位数外层个位内层十位传递到函数里,循环判断如果到i和j组成的两位数等于这个传递进来的id就把它赋值给数组的第i(外层索引)个元素上。
相应的isActive[index]==index+''+typeIndex也会响应样式


** 坑 **

vue数据双向绑定依赖于Object.defineProperty( ),而这个东西对数组的变动无法检测,所以你的arr[i]怎么变,对vue来说它不知道,当然视图也不会跟新;
将筛选的arrry先用一个数组arr保存,然后一次性this.isActive = arr(引用数居的指针变了,vue会对这个值重新init,视图会更新)
直接赋值浅拷贝还是对数组索引赋值的引用,所以得用深拷贝的方式给isActive赋值。