微信小程序实战篇:商品属性联动选择(案例)

本期的微信小程序实战篇来做一个电商网站经常用到的-商品属性联动选择的效果,素材参考了一点点奶茶。

效果演示:

商品属性联动.gif

代码示例

1、commodity.xml
 
<!-- <view class="title">属性值联动选择</view>   -->
<!--options-->
<view class="commodity_attr_list"> <!--每组属性--> <view class="attr_box" wx:for="{{attrValueList}}" wx:for-item="attrValueObj" wx:for-index="attrIndex"> <!--属性名--> <view class="attr_name">{{attrValueObj.attrKey}}</view> <!--属性值--> <view class="attr_value_box"> <!--每个属性值--> <view class="attr_value {{attrIndex==firstIndex || attrValueObj.attrValueStatus[valueIndex]?(value==attrValueObj.selectedValue?'attr_value_active':''):'attr_value_disabled'}}" bindtap="selectAttrValue" data-status="{{attrValueObj.attrValueStatus[valueIndex]}}" data-value="{{value}}" data-key="{{attrValueObj.attrKey}}" data-code="{{attrCode}}" data-index="{{attrIndex}}" data-selectedvalue="{{attrValueObj.selectedValue}}" wx:for="{{attrValueObj.attrValues}}" wx:for-item="value" wx:for-index="valueIndex">{{value}}</view> </view> </view> </view> <!--button--> <view class="weui-btn-area"> <button class="weui-btn" bindtap="submit">选好了 </button> </view> 

上述代码把页面盒子分为两部分commodity_attr_listweui-btn-area
commodity_attr_list:循环获取商品的属性名和相对应的属性值,并布局页面。
weui-btn-area:提交校验并获取选中商品属性结果。

2、commodity.js

数据结构

    //数据结构:以一组一组的数据来进行设定 commodityAttr: [{priceId: 1,price: 35.0,"stock": 8, "attrValueList": [ { "attrKey": "规格:", "attrValue": " 免费配料", "attrCode": "1001" }, { "attrKey": "甜度:", "attrValue": "七分甜", "attrCode": "2001" }, { "attrKey": "加料:", "attrValue": "珍珠", "attrCode": "3001" }, { "attrKey": "冰块:", "attrValue": "少冰", "attrCode": "4001" } ] }, { priceId: 2, price: 35.1, "stock": 9, "attrValueList": [ { "attrKey": "规格:", "attrValue": " 燕麦", "attrCode": "1002" }, { "attrKey": "甜度:", "attrValue": "五分甜", "attrCode": "2002" }, { "attrKey": "加料:", "attrValue": "椰果", "attrCode": "3002" }, { "attrKey": "冰块:", "attrValue": "去冰", "attrCode": "4002" } ] }, { priceId: 3, price: 35.2, "stock": 10, "attrValueList": [ { "attrKey": "规格:", "attrValue": " 布丁", "attrCode": "1003" }, { "attrKey": "甜度:", "attrValue": "无糖", "attrCode": "2003" }, { "attrKey": "加料:", "attrValue": "仙草", "attrCode": "3003" }, { "attrKey": "冰块:", "attrValue": "常温", "attrCode": "4003" } ] }, { priceId: 4, price: 35.2, "stock": 10, "attrValueList": [ { "attrKey": "规格:", "attrValue": "再加一份奶霜", "attrCode": "1004" }, { "attrKey": "甜度:", "attrValue": "无糖", "attrCode": "2003" }, { "attrKey": "加料:", "attrValue": "仙草", "attrCode": "3004" }, { "attrKey": "冰块:", "attrValue": "热饮", "attrCode": "4004" } ] }, { priceId: 5, price: 35.2, "stock": 10, "attrValueList": [ { "attrKey": "规格:", "attrValue": " 免费配料", "attrCode": "1004" }, { "attrKey": "甜度:", "attrValue": "五分甜", "attrCode": "2003" }, { "attrKey": "加料:", "attrValue": "椰果", "attrCode": "3004" }, { "attrKey": "冰块:", "attrValue": "常温", "attrCode": "4004" } ] } ], attrValueList: [] } 

属性选中和取消选择效果处理

onShow: function () {this.setData({ includeGroup: this.data.commodityAttr }); this.distachAttrValue(this.data.commodityAttr); // 只有一个属性组合的时候默认选中 // console.log(this.data.attrValueList); if (this.data.commodityAttr.length == 1) { for (var i = 0; i < this.data.commodityAttr[0].attrValueList.length; i ) { this.data.attrValueList[i].selectedValue = this.data.commodityAttr[0].attrValueList[i].attrValue; } this.setData({ attrValueList: this.data.attrValueList }); } }, /* 获取数据 */ distachAttrValue: function (commodityAttr) { /** 将后台返回的数据组合成类似 { attrKey:'型号', attrValueList:['1','2','3'] } */ // 把数据对象的数据(视图使用),写到局部内 var attrValueList = this.data.attrValueList; // 遍历获取的数据 for (var i = 0; i < commodityAttr.length; i ) { for (var j = 0; j < commodityAttr[i].attrValueList.length; j ) { var attrIndex = this.getAttrIndex(commodityAttr[i].attrValueList[j].attrKey, attrValueList); // console.log('属性索引', attrIndex); // 如果还没有属性索引为-1,此时新增属性并设置属性值数组的第一个值;索引大于等于0,表示已存在的属性名的位置 if (attrIndex >= 0) { // 如果属性值数组中没有该值,push新值;否则不处理 if (!this.isValueExist(commodityAttr[i].attrValueList[j].attrValue, attrValueList[attrIndex].attrValues)) { attrValueList[attrIndex].attrValues.push(commodityAttr[i].attrValueList[j].attrValue); } } else { attrValueList.push({ attrKey: commodityAttr[i].attrValueList[j].attrKey, attrValues: [commodityAttr[i].attrValueList[j].attrValue] }); } } } // console.log('result', attrValueList) for (var i = 0; i < attrValueList.length; i ) { for (var j = 0; j < attrValueList[i].attrValues.length; j ) { if (attrValueList[i].attrValueStatus) { attrValueList[i].attrValueStatus[j] = true; } else { attrValueList[i].attrValueStatus = []; attrValueList[i].attrValueStatus[j] = true; } } } this.setData({ attrValueList: attrValueList }); }, getAttrIndex: function (attrName, attrValueList) { // 判断数组中的attrKey是否有该属性值 for (var i = 0; i < attrValueList.length; i ) { if (attrName == attrValueList[i].attrKey) { break; } } return i < attrValueList.length ? i : -1; }, isValueExist: function (value, valueArr) { // 判断是否已有属性值 for (var i = 0; i < valueArr.length; i ) { if (valueArr[i] == value) { break; } } return i < valueArr.length; }, /* 选择属性值事件 */ selectAttrValue: function (e) { /* 点选属性值,联动判断其他属性值是否可选 { attrKey:'型号', attrValueList:['1','2','3'], selectedValue:'1', attrValueStatus:[true,true,true] } console.log(e.currentTarget.dataset); */ var attrValueList = this.data.attrValueList; var index = e.currentTarget.dataset.index;//属性索引 var key = e.currentTarget.dataset.key; var value = e.currentTarget.dataset.value; if (e.currentTarget.dataset.status || index == this.data.firstIndex) { if (e.currentTarget.dataset.selectedvalue == e.currentTarget.dataset.value) { // 取消选中 this.disSelectValue(attrValueList, index, key, value); } else { // 选中 this.selectValue(attrValueList, index, key, value); } } }, /* 选中 */ selectValue: function (attrValueList, index, key, value, unselectStatus) { // console.log('firstIndex', this.data.firstIndex); var includeGroup = []; if (index == this.data.firstIndex && !unselectStatus) { // 如果是第一个选中的属性值,则该属性所有值可选 var commodityAttr = this.data.commodityAttr; // 其他选中的属性值全都置空 // console.log('其他选中的属性值全都置空', index, this.data.firstIndex, !unselectStatus); for (var i = 0; i < attrValueList.length; i ) { for (var j = 0; j < attrValueList[i].attrValues.length; j ) { attrValueList[i].selectedValue = ''; } } } else { var commodityAttr = this.data.includeGroup; } // console.log('选中', commodityAttr, index, key, value); for (var i = 0; i < commodityAttr.length; i ) { for (var j = 0; j < commodityAttr[i].attrValueList.length; j ) { if (commodityAttr[i].attrValueList[j].attrKey == key && commodityAttr[i].attrValueList[j].attrValue == value) { includeGroup.push(commodityAttr[i]); } } } attrValueList[index].selectedValue = value; // 判断属性是否可选 for (var i = 0; i < attrValueList.length; i ) { for (var j = 0; j < attrValueList[i].attrValues.length; j ) { attrValueList[i].attrValueStatus[j] = false; } } for (var k = 0; k < attrValueList.length; k ) { for (var i = 0; i < includeGroup.length; i ) { for (var j = 0; j < includeGroup[i].attrValueList.length; j ) { if (attrValueList[k].attrKey == includeGroup[i].attrValueList[j].attrKey) { for (var m = 0; m < attrValueList[k].attrValues.length; m ) { if (attrValueList[k].attrValues[m] == includeGroup[i].attrValueList[j].attrValue) { attrValueList[k].attrValueStatus[m] = true; } } } } } } // console.log('结果', attrValueList); this.setData({ attrValueList: attrValueList, includeGroup: includeGroup }); var count = 0; for (var i = 0; i < attrValueList.length; i ) { for (var j = 0; j < attrValueList[i].attrValues.length; j ) { if (attrValueList[i].selectedValue) { count ; break; } } } if (count < 2) {// 第一次选中,同属性的值都可选 this.setData({ firstIndex: index }); } else { this.setData({ firstIndex: -1 }); } }, /* 取消选中 */ disSelectValue: function (attrValueList, index, key, value) { var commodityAttr = this.data.commodityAttr; attrValueList[index].selectedValue = ''; // 判断属性是否可选 for (var i = 0; i < attrValueList.length; i ) { for (var j = 0; j < attrValueList[i].attrValues.length; j ) { attrValueList[i].attrValueStatus[j] = true; } } this.setData({ includeGroup: commodityAttr, attrValueList: attrValueList }); for (var i = 0; i < attrValueList.length; i ) { if (attrValueList[i].selectedValue) { this.selectValue(attrValueList, i, attrValueList[i].attrKey, attrValueList[i].selectedValue, true); } } } 

结果提交

submit: function () {var value = []; for (var i = 0; i < this.data.attrValueList.length; i ) { if (!this.data.attrValueList[i].selectedValue) { break; } value.push(this.data.attrValueList[i].selectedValue); } if (i < this.data.attrValueList.length) { wx.showToast({ title: '请选择完整!', icon: 'loading', duration: 1000 }) } else { var valueStr = ""; for(var i = 0;i < value.length;i ){ console.log(value[i]); valueStr = value[i] ","; } wx.showModal({ title: '提示', content: valueStr, success: function (res) { if (res.confirm) { console.log('用户点击确定') } else if (res.cancel) { console.log('用户点击取消') } } }) console.log(valueStr); } } 
3、commodity.wxss
.title { padding: 10rpx 20rpx; margin: 10rpx 0; border-left: 4rpx solid #ccc; } /*全部属性的主盒子*/ .commodity_attr_list { background: #fff; padding: 0 20rpx; font-size: 26rpx; overflow: hidden; width: 100%; } /*每组属性的主盒子*/ .attr_box { width: 100%; overflow: hidden; border-bottom: 1rpx solid #ececec; display: flex; flex-direction: column; } /*属性名*/ .attr_name { width: 20%; float: left; padding: 15rpx 0; } /*属性值*/ .attr_value_box { width: 80%; float: left; padding: 15rpx 0; overflow: hidden; } /*每个属性值*/ .attr_value { float: left; padding: 0 30rpx; margin: 10rpx 10rpx; border: 1rpx solid #ececec; border-radius:5px; line-height:30px; } /*每个属性选中的当前样式*/ .attr_value_active { border-radius: 10rpx; color: #0089dc; padding: 0 30rpx; border: 1rpx solid #0089dc; /* background: #fff; */ } /*禁用属性*/ .attr_value_disabled { color: #ccc; } /*button*/ .weui-btn-area { margin: 1.17647059em 15px 0.3em; } .weui-btn{ width: 80%; height: 100rpx; border-radius: 3rpx; background-color:#0089dc; color: #fff; } 

好了,复制上述代码就可以实现效果哦,赶紧试试吧!



作者:IT实战联盟Lin
链接:https://www.jianshu.com/p/f7f5f593b8e3
來源:简书
简书著作权归作者所有,任何形式的转载都请联系作者获得授权并注明出处。

更多专业前端知识,请上 【猿2048】www.mk2048.com

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/364755.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

Spring JMS:处理事务中的消息

1.引言 这篇文章将向您展示在使用JMS异步接收消息期间&#xff0c;使用者执行过程中的错误如何导致消息丢失。 然后&#xff0c;我将解释如何使用本地事务解决此问题。 您还将看到这种解决方案在某些情况下可能导致消息重复&#xff08;例如&#xff0c;当它将消息保存到数据库…

Linux下Python编译安装

1.安装python3 1.1下载python源码包 网址&#xff1a;https://www.python.org/downloads/release/python-362/ 下载地址&#xff1a;https://www.python.org/ftp/python/3.6.2/Python-3.6.2.tgz 1.1.1安装python前的库环境&#xff0c;非常重要 yum install gcc patch libffi-d…

OO第二单元作业总结

一&#xff1a;设计策略 第一次作业&#xff1a;第一次是单电梯傻瓜调度策略&#xff0c;因此我把调度器当作共享资源对象&#xff0c;有一个put和一个get方法&#xff0c;因为只有一个电梯&#xff0c;并且单次取出和投放一个请求&#xff0c;因此只需要同步控制一下这两个方法…

jmeter找不到java.dll_Windows下Jmeter安装出现Not able to find Java executable or version问题解决方案...

最近在做一个开放接口平台性能测试 , 指标是最少达到1000/s的并发 , 接口鉴权 百万级的表 在1s内完成..在众多压测工具中 ,,选择了Apache的jmeter ,于官网下载了最新版本http://jmeter.apache.org/download_jmeter.cgi (jmeter下载地址)由于jmeter运行是基于java的,所以需要…

迭代加深搜索 C++解题报告 :[SCOI2005]骑士精神

题目 此题根据题目可知是迭代加深搜索。 首先应该枚举空格的位置&#xff0c;让空格像一个马一样移动。 但迭代加深搜索之后时间复杂度还是非常的高&#xff0c;根本过不了题。 感觉也想不出什么减枝&#xff0c;于是便要用到了乐观估计函数&#xff08;Optimistic Estimation …

一个web项目web.xml的配置中context-param配置作用

<context-param>的作用:web.xml的配置中<context-param>配置作用1. 启动一个WEB项目的时候,容器(如:Tomcat)会去读它的配置文件web.xml.读两个节点: <listener></listener> 和 <context-param></context-param>2.紧接着,容器创建一个Servl…

51Nod 1362 搬箱子 —— 组合数(非质数取模) (差分TLE)

题目&#xff1a;http://www.51nod.com/Challenge/Problem.html#!#problemId1362 首先&#xff0c;\( f[i][j] \) 是一个 \( i \) 次多项式&#xff1b; 如果考虑差分&#xff0c;用一个列向量维护 0 次差分到 \( n \) 次差分即可&#xff0c;在第 \( n \) 次上差分数组已经是一…

错误处理在Spring Integration中如何工作

1.引言 这篇文章的目标是向您展示将消息传递系统与Spring Integration结合使用时如何处理错误。 您将看到同步和异步消息传递之间的错误处理有所不同。 和往常一样&#xff0c;我将跳过聊天并继续进行一些示例。 您可以在github上获取源代码。 2&#xff0c;样品申请 我将使用…

原生js、jQuery实现选项卡功能

在大家在网上平常浏览网页的时候&#xff0c;想必各位都会看到选项卡功能&#xff0c;在这里给大家详解一下用原生js、jQuery如何来写一些基本的选项卡 话不多说&#xff0c;先给各位看一下功能图&#xff1a; 好了&#xff0c;下边开始写代码了&#xff1a; HTML代码&#x…

.NET core2.0 发布至IIS中

.NET CORE和asp.net 发布时不太一样&#xff0c;ASP.NET Core不再是由IIS工作进程&#xff08;w3wp.exe&#xff09;托管&#xff0c;而是使用自托管Web服务器&#xff08;Kestrel&#xff09;运行&#xff0c;IIS则是作为反向代理的角色转发请求到Kestrel不同端口的ASP.NET Co…

如何用纯 CSS 创作一个文本淡入淡出的 loader 动画

效果预览 在线演示 按下右侧的“点击预览”按钮可以在当前页面预览&#xff0c;点击链接可以全屏预览。https://codepen.io/comehope/pen/ERwpeG可交互视频此视频是可以交互的&#xff0c;你可以随时暂停视频&#xff0c;编辑视频中的代码。请用 chrome, safari, edge 打开观…

《机器学习基石》第一周 —— When Can Machine Learn?

&#xff08;注&#xff1a;由于之前进行了吴恩达机器学习课程的学习&#xff0c;其中有部分内容与机器学习基石的内容重叠&#xff0c;所以以下该系列的笔记只记录新的知识&#xff09; 《机器学习基石》课程围绕着下面这四个问题而展开&#xff1a; 主要内容&#xff1a; 一、…

如何用纯 CSS 创作一盘传统蚊香

效果预览 在线演示 按下右侧的“点击预览”按钮可以在当前页面预览&#xff0c;点击链接可以全屏预览。https://codepen.io/comehope/pen/BVpvMz可交互视频教程此视频是可以交互的&#xff0c;你可以随时暂停视频&#xff0c;编辑视频中的代码。请用 chrome, safari, edge 打…

[Unity3D]Unity3D游戏开发之怪物AI

大家好。欢迎大家关注由我为大家带来的Unity3D游戏开发系列文章&#xff0c;我的博客地址为&#xff1a;http://blog.csdn.net/qinyuanpei。在上一篇文章中&#xff0c;我们基本上实现了一个小地图的功能&#xff0c;今天呢&#xff0c;我们来实现怪物AI&#xff0c;所谓怪物AI…

如何把握好 transition 和 animation 的时序,创作描边按钮特效

效果预览 在线演示 按下右侧的“点击预览”按钮可以在当前页面预览&#xff0c;点击链接可以全屏预览。https://codepen.io/comehope/pen/mKdzZM可交互视频教程此视频是可以交互的&#xff0c;你可以随时暂停视频&#xff0c;编辑视频中的代码。请用 chrome, safari, edge 打…

使用PHREAK算法实现Drools 6性能

Drools 6引入了新的惰性匹配算法。 该算法的详细信息已在之前的两个博客中介绍&#xff1a; RIP RETE时间获得PHREAKY 基于PHREAK堆栈的评估和向后链接 第一篇文章讨论了性能以及为什么算法的批处理和惰性方面难以比较。 “性能的最后一点。 通常&#xff0c;使用PHREAK的单…

PAT 1131 Subway Map

题目链接&#xff1a; https://pintia.cn/problem-sets/994805342720868352/problems/994805347523346432 思路&#xff1a; 说多了都是泪&#xff0c; Dijstra超时&#xff0c;采用dfs 利用map<pair<int,int>,int>&#xff0c;表示两个点和他们中间的地铁线号 每次…

专访Vue作者尤雨溪:Vue CLI 3.0重构的原因

1、为什么要对 Vue CLI 进行大规模修改&#xff1f; 尤雨溪认为旧版本的 Vue CLI 本质上只是从 GitHub 拉取模版&#xff0c;这种拉模版的方式有几个问题&#xff1a; &#xff08;1&#xff09; 在单个模版里面同时支持太多选项会导致模版本身变得极其复杂和难以维护&#x…

java秒杀时间与服务器时间_Javascript实现秒杀倒计时(时间与服务器时间同步)...

现在有很多网站都在做秒杀商品&#xff0c;而这其中有一个很重要的环节就是倒计时。关于倒计时&#xff0c;有下面几点需要注意&#xff1a;1.应该使用服务器时间而不是本地时间(本地时间存在时区不同、用户自行设置等问题)。2.要考虑网络传输的耗时。3.获取时间时可直接从AJAX…

Python3.5-20190501-廖老师的

python是一门解释型\脚本语言(和js特别像,如果同时学习js和python完全搅浑了.) 在运行py时候是一句一句翻译成cpu识别的机器码,所以速度比较慢.而C程序是运行前直接编译成CPU能执行的机器码&#xff0c;所以非常快. 学习python,就需要安装python.安装的同时会有一个解释器,就是…