乐趣区

微信小程序中遇到的多规格问题(一)

刚进入公司的时候就有遇到过多规格的问题,当时就觉得很麻烦,就只是看了下,没有尝试,最近在写微信小程序的时候,又遇到了多规格问题,就自己尝试了下,在这里记录下
1. 效果图

2. 文件及部分思路
index.wxml 文件
<view class=”multipleStandard” bindtap=”standardSelect”>
<view class=”standard”>
规格:
<text class=”item”> 颜色 </text>
<text class=”item”> 颜色 </text>
<text class=”item”> 颜色 </text>
</view>
<image src=”/images/arrows.png” class=”arrows”></image>
</view>
<view style=”background:rgb(207, 224, 232); height: 300rpx;margin-top: 50rpx;”></view>
<view animation=”{{animationData}}” class=”selectStandard” catchtouchmove=”noMove”>
<view class=”tophead”>
<view class=”topimg”>
<image src=”{{goods.original_img}}”></image>
</view>
<view class=”topright”>
<view class=”selectClose”>
<view style=”color:#ef5426;”>{{standardObject.price}}</view>
<image src=”/images/close.png” bindtap=”handleClose”></image>
</view>
<view style=”margin:10rpx 0;color:#999999;”> 库存:{{standardObject.store_count}}</view>
<view> 规格: {{mergeStandard}}</view>
</view>
</view>
<view class=”standard” wx:for=”{{commodityStandard}}” wx:key=”{{standardIndex}}” wx:for-index=”standardIndex”>
<view class=”standardTitle”>{{item[0].spec_name}}</view>
<view class=”standardItem”>
<block wx:for=”{{item}}” wx:key=”{{item.item_id}}”>
<view class=”selectItem {{isSelect[item.isClick]}}” bindtap=”handleStandardClick” data-standard-index=”{{standardIndex}}” data-index=”{{index}}” data-id=”{{item.item_id}}”>{{item.item}}</view>
</block>
</view>
<view style=”height:1px; width:100%;background-color:#eeeeee;”></view>
</view>
<view class=”selectCount”>
<view class=”countname”> 数量 </view>
<view class=”countright”>
<i-input-number value=”{{commodityNum}}” min=”1″ max=”{{store_count}}” bindchange=”handleCommodityNumber” />
</view>
</view>
<view class=”submitBtn” bindtap=”submitSelected”>
确定
</view>
</view>
<i-message id=”message” />
index.wxss 文件
.multipleStandard{
display: flex;
margin-top: 20rpx;
padding: 15rpx 20rpx;
justify-content: space-between;
align-items: center;
box-shadow: 0 0 10px #ccc;
}
.item{
margin-right: 15rpx;
}
.arrows{
width: 16rpx;
height: 27rpx;
}

/* 规格弹窗 */
.selectStandard {
width: 100%;
height: 1000rpx;
background-color: #fff;
position: fixed;
z-index: 333;
bottom: -600px;
border-top-left-radius: 20rpx;
border-top-right-radius: 20rpx;
}

/* 头部选中的规格 */
.tophead {
display: flex;
margin: 30rpx 3%;
width: 94%;
align-items: center;
text-align: center;
}

.topimg {
width: 200rpx;
height: 200rpx;
}

.topimg image {
width: 100%;
height: 100%;
border-radius: 20rpx;
background-color: red;
}

.topright {
margin-left: 30rpx;
font-size: 28rpx;
text-align: left;
width: 66%;
}
/* 关闭按钮 */
.selectClose {
display: flex;
justify-content: space-between;
align-items: center;
}

.selectClose image {
width: 30rpx;
height: 30rpx;
}

.standard {
margin: 0 3%;
width: 94%;
font-size: 28rpx;
}

.standardTitle {
font-size: 30rpx;
margin-top: 20rpx;
}
.standardItem {
display: flex;
flex-wrap: wrap;
width: 100%;
}
.selectItem {
border: solid 1px #666;
margin: 20rpx;
padding: 5rpx 23rpx;
border-radius: 16rpx;
}
/* 规格选中时样式 */
.standardSelected{
color: #fff;
background: #f26740;
background-color:#fe6732;
border:solid 1px #fe6732;
margin:20rpx;
padding:5rpx 23rpx;
border-radius:16rpx;
}
.standardNormal{
color: #000;
}
.standardDisable{
color: #eee;
}

/* 选择的数量 */
.selectCount {
margin: 30rpx 3%;
width: 94%;
font-size: 28rpx;
}
.countright {
float: right;
display: flex;
text-align: center;
align-items: center;
}

.countname {
margin-bottom: 20rpx;
font-size: 30rpx;
}

.submitBtn {
position: absolute;
bottom: 0;
width: 70%;
margin: 0 15% 20rpx 15%;
text-align: center;
z-index: 66;
height: 80rpx;
background-color: #fe6732;
border-radius: 40rpx;
color: white;
font-size: 32rpx;
line-height: 80rpx;
}
index.js 文件
const {
$Message
} = require(‘../../component/iview/base/index’);
Page({
data: {
animationData: {},
isSelect: [“standardNormal”, “standardSelected”, “standardDisable”], /* 用于区别当前的规格是否选中 */
goods: {
goods_name: “ 男鞋 ”,
store_count: 158,
cost_price: “10.00”,
original_img: “/images/commodity.jpg”,
},
commodityStandard: [
[
{
spec_name: “ 颜色 ”,
item_id: 535385,
item: “ 白色 ”,
src: “”,
isClick: 0
},
{
spec_name: “ 颜色 ”,
item_id: 535386,
item: “ 黑色 ”,
src: “”,
isClick: 0
}
],
[
{
spec_name: “ 尺寸 ”,
item_id: 535692,
item: “170”,
src: “”,
isClick: 0
},
{
spec_name: “ 尺寸 ”,
item_id: 535693,
item: “180”,
src: “”,
isClick: 0
}
],
[
{
spec_name: “ 重量 ”,
item_id: 552569,
item: “11”,
src: “”,
isClick: 0
},
{
spec_name: “ 重量 ”,
item_id: 552570,
item: “15”,
src: “”,
isClick: 0
}
]
],
standardInfo: [
{
id: 1018269,
key: “535385_535692_552569”,
price: “10.00”,
productprice: “0.00”,
store_count: 20
},
{
id: 1018270,
key: “535385_535692_552570”,
price: “20.00”,
productprice: “0.00”,
store_count: 20
},
{
id: 1018271,
key: “535385_535693_552569”,
price: “30.00”,
productprice: “0.00”,
store_count: 20
},
{
id: 1018272,
key: “535385_535693_552570”,
price: “40.00”,
productprice: “0.00”,
store_count: 20
},
{
id: 1018273,
key: “535386_535692_552569”,
price: “50.00”,
productprice: “0.00”,
store_count: 20
},
{
id: 1018274,
key: “535386_535692_552570”,
price: “60.00”,
productprice: “0.00”,
store_count: 20
},
{
id: 1018275,
key: “535386_535693_552569”,
price: “70.00”,
productprice: “0.00”,
store_count: 20
},
{
id: 1018276,
key: “535386_535693_552570”,
price: “80.00”,
productprice: “0.00”,
store_count: 18
}
],
selectedId: [],
selectedStandard: [],
standardObject: {},
commodityNum: 1,
},
onLoad: function (options) {
let goods = this.data.goods;
let standardObject = this.data.standardObject;
standardObject.price = goods.cost_price;
standardObject.store_count = goods.store_count;
let store_count = goods.store_count;
this.setData({
standardObject,
store_count
})
},
/* 规格选择 */
standardSelect() {
var that = this
var animal1 = wx.createAnimation({
timingFunction: ‘ease-in’
}).translate(0, -600).step({
duration: 300
})
that.setData({
animationData: animal1.export(),
})
},
/* 关闭规格选择 */
handleClose() {
var that = this
var animal1 = wx.createAnimation({
timingFunction: ‘ease-in’
}).translate(0, 600).step({
duration: 300
})
that.setData({
animationData: animal1.export()
})
},
/* 每个规格的点击事件 */
handleStandardClick(e) {
let id = e.currentTarget.dataset.id;
// 总规格名称索引
let standardIndex = e.currentTarget.dataset.standardIndex;
// 单个规格名称索引
let index = e.currentTarget.dataset.index;
let commodityStandard = this.data.commodityStandard;
let standardLength = commodityStandard[standardIndex].length;

// 用于存储规格的 id
let selectedId = this.data.selectedId;
// 用总规格名称索引来存储每个选中的规格 id
selectedId[standardIndex] = id;

let selectedStandard = this.data.selectedStandard;

// 在点击的时候,只需要对点击的这个规格所在的数组进行循环
for (let i = 0; i < standardLength; i++) {
// 找到对应的单个规格索引,并设置 isClick 及单个规格名称
if (index == i) {
commodityStandard[standardIndex][index].isClick = 1;
selectedStandard[standardIndex] = commodityStandard[standardIndex][index].item;
} else {
commodityStandard[standardIndex][i].isClick = 0;
}
}

// 将 id 用_连接起来
let mergeId = selectedId.join(‘_’);
console.log(mergeId);
let mergeStandard = selectedStandard.join(‘ ‘);
console.log(mergeStandard);

let standardInfo = this.data.standardInfo;
let standardInfoLength = standardInfo.length;
// 用于存储选中的规格
let standardObject = {};

for (let i = 0; i < standardInfoLength; i++) {
if (standardInfo[i].key == mergeId) {
standardObject = standardInfo[i];
break;
} else {
standardObject = this.data.standardObject;
}
}

this.setData({
currentId: id,
commodityStandard,
selectedId,
standardObject,
mergeStandard,
selectedStandard,
})

},
/* 选择数量 */
handleCommodityNumber(e) {
let commodityNum = e.detail.value;
if (commodityNum >= this.data.store_count) {
commodityNum = this.data.store_count;
}
this.setData({
commodityNum
})
},
/* 保存选择的规格 */
submitSelected() {
let selectedStandard = this.data.selectedStandard;
let length = selectedStandard.length;
console.log(length)
if (length == 0) {
$Message({
content: ‘ 请选择规格 ’,
type: ‘error’
});
return false;
}
for (let i = 0; i < length; i++) {
if (length < this.data.commodityStandard.length) {
$Message({
content: ‘ 请选择规格 ’,
type: ‘error’
});
break;
}
if (selectedStandard[i] == undefined) {
$Message({
content: ‘ 请选择规格 ’,
type: ‘error’
});
break;
}
}
$Message({
content: ‘ 选择成功 ’,
type: ‘success’
});
},
})
我这里提示信息使用了插件 iview,可以在官网直接下载后使用
iview weapp
3. 部分思路及改进方法
开始想到的是将需合并的 id 的位置写死,比如,第一个位置就传第一个规格里选中的规格 id,第二个位置就传第二个规格里选中的规格 id, 不过此时有问题,就是后台的 id 拼接是根据当前规格长度来拼接的,从最短的开始往长的拼接,然后,长度相等的时候,我这边的话,后台是从第一个开始拼接的,而且你选规格时,也可能是随机点的,此时若是采用第一种位置写死的方法就会有问题,因为会找不到对应的合并后的规格 id

因为我这里一开始用的数据就刚好满足我的设想,但是后面换了个数据后就出现问题了
index.wxml 文件也做部分修改, 可以直接查找下,类名为 standardItem

<view class=”standardItem”>
<block wx:for=”{{item}}” wx:key=”{{item.item_id}}”>
<view class=”selectItem {{item.item_id == Specifications[standardIndex]?’standardSelected’:’standardNormal’}}” bindtap=”handleStandardClick” data-standard-index=”{{standardIndex}}” data-name=”{{item.item}}” data-id=”{{item.item_id}}”>{{item.item}}</view>
</block>
</view>
* 增加另一种模拟数据
goods: {
goods_name: “ 男鞋 ”,
store_count: 95,
market_price: “10.00”,
shop_price: “101.00”,
cost_price: “10.00”,
original_img: “/images/commodity.jpg”,
store_id: 170,
},
commodityStandard: [
[
{
spec_name: “ 颜色 ”,
item_id: 532825,
item: “ 白色 ”,
src: “”,
isClick: 0
},
{
spec_name: “ 颜色 ”,
item_id: 532826,
item: “ 黑色 ”,
src: “”,
isClick: 0
},
{
spec_name: “ 颜色 ”,
item_id: 532827,
item: “ 红色 ”,
src: “”,
isClick: 0
}
],
[
{
spec_name: “ 大小 ”,
item_id: 532828,
item: “160”,
src: “”,
isClick: 0
},
{
spec_name: “ 大小 ”,
item_id: 532829,
item: “150”,
src: “”,
isClick: 0
}
],
[
{
spec_name: “ 重量 ”,
item_id: 552581,
item: “10”,
src: “”,
isClick: 0
}
]
],
/* 这里合并规格的信息 */
spec_goods_price: [
{
id: 1018286,
key: “552581_532828_532825”,
price: “10.00”,
productprice: “0.00”,
store_count: 9
},
{
id: 1018287,
key: “552581_532828_532826”,
price: “20.00”,
productprice: “0.00”,
store_count: 10
},
{
id: 1018288,
key: “552581_532828_532827”,
price: “30.00”,
productprice: “0.00”,
store_count: 10
},
{
id: 1018289,
key: “552581_532829_532825”,
price: “40.00”,
productprice: “0.00”,
store_count: 10
},
{
id: 1018290,
key: “552581_532829_532826”,
price: “50.00”,
productprice: “0.00”,
store_count: 7
},
{
id: 1018291,
key: “552581_532829_532827”,
price: “60.00”,
productprice: “0.00”,
store_count: 10
}
],
index.js 文件
onLoad: function (options) {
let goods = this.data.goods;
/* 用于存储对应的价格及库存 */
let standardObject = this.data.standardObject;
standardObject.price = goods.cost_price;
standardObject.store_count = goods.store_count;

let spec_goods_price =this.data.spec_goods_price;
if (spec_goods_price) {
this.checkPrice(spec_goods_price);
}
this.setData({
standardObject,
})
},
handleStandardClick: function (e) {
// 总规格名称索引
let standardIndex = e.currentTarget.dataset.standardIndex;
let id = e.currentTarget.dataset.id;
/* 存储选中的规格名称 */
let name = e.currentTarget.dataset.name;
let selectedStandard = this.data.selectedStandard;
selectedStandard[standardIndex] = name;
let mergeStandard = selectedStandard.join(‘ ‘);
let Specifications = this.data.Specifications;
Specifications[standardIndex] = id;
console.log(mergeStandard)
this.setData({
Specifications,
mergeStandard,
selectedStandard,
})
this.checkPrice(this.data.spec_goods_price);
},
/* 在还未选择完规格时,暂时选用第一个合并后的规格价格及库存 */
checkPrice: function (spec_goods_price) {
let standardObject = this.data.standardObject;
if (!this.checkSpecifications(spec_goods_price)) {
standardObject.price = spec_goods_price[0].price;
standardObject.store_count = spec_goods_price[0].store_count;
this.setData({
standardObject,
})
}
},
/* 保存及校验是否选好了规格 */
submitSelected: function (e) {
let spec_goods_price = this.data.spec_goods_price;
let i = 0;
let optionid = “”;
if (spec_goods_price) {
optionid = this.checkSpecifications();
if (optionid) {
$Message({
content: ‘ 选择成功 ’,
type: ‘success’
});
} else {
$Message({
content: ‘ 请选择规格 ’,
type: ‘error’
});
}
}
},
checkSpecifications(spec_goods) {
let spec_goods_price = spec_goods || this.data.spec_goods_price;
let Specifications = this.data.Specifications;
let SpecificationsLength = spec_goods_price[0].key.split(“_”).length;
let standardObject = this.data.standardObject;
if (Specifications.length != SpecificationsLength) {
return false;
} else {
for (let i = 0; i < spec_goods_price.length; i++) {
/* 若 selectSpecifications 全为 true,则选中了对应的合并后的规格 */
let selectSpecifications = true;
for (let j = 0; j < Specifications.length; j++) {
if (spec_goods_price[i].key.indexOf(Specifications[j]) == -1) {
selectSpecifications = false;
break;
}
}
if (selectSpecifications) {
standardObject.price = spec_goods_price[i].price;
standardObject.store_count = spec_goods_price[i].store_count;
this.setData({
standardObject,
})
return spec_goods_price[i].id;
}
}
}
return false;
},
利用 indexOf 来判断合并后的 key 值,就不用通过写死位置存储规格,然后这里用了动画,可以自己查看官方完档微信创建动画

这里的规格啥的,格式可能会是多样的,我这里的话,就是返回这样的格式,其实我还想实现就是根据库存来判断是否可以点击,比如选尺码 28,然后可能颜色为黑色的就库存不足,此时,是不能让他点击的,日后会在做下这个功能,欢迎大家在评论区指正,共同进步 ^_^

正在努力学习中,若对你的学习有帮助,留下你的印记呗(点个赞咯 ^_^)

往期好文推荐:

判断 ios 和 Android 及 PC 端
纯 css 实现瀑布流(multi-column 多列及 flex 布局)
实现文字的省略号

退出移动版