0


前端商品SKU的选择

前端商品SKU的选择

前言

作为一枚后端程序猿,一直没有对前端写商品规格选择部分思考过,现在总结一下自己的想法。

原文地址:https://blog.csdn.net/weixin_49431241/article/details/134421114

实现效果

效果图

一、html

<template><viewclass="productConten"><viewv-for="(spec, specIndex) in specList":key="specIndex"><viewclass="productTitle">{{ spec.name }}</view><viewclass="productItem"><viewv-for="(specItem, specItemIndex) in spec.item":key="specItemIndex":class="[specItemIndex == selectedAttrIndex[specIndex] ? 'active' : '', specItem.checked ? '' : 'noneActive']"@click="selectArrtBtn(specItem, specItemIndex, specIndex)">
                    {{ specItem.name }}
                </view></view></view><view><text>{{ selectSpec }}</text></view></view></template>

二、style

<stylelang="scss">.container{padding: 20px;font-size: 14px;line-height: 24px;}.productConten{width: 500px;padding: 40px;.productTitle{font-weight: 500;margin: 10px 0;}.productItem{display: flex;margin-bottom: 30px;view{background: #fff;color: #000;padding: 4px 10px;border: 1px solid #eee;margin-right: 10px;}}}.noneActive{background-color: #ccc;opacity: 0.4;color: #000;pointer-events: none;}.active{background-color: #c41e3a !important;color: #fff !important;border: 1px solid #c41e3a !important;}</style>

三、 js部分

<script>exportdefault{data(){return{specList:[{name:'颜色',item:[{name:'白色'},{name:'黑色'},{name:'红色'}]},{name:'尺码',item:[{name:'x'},{name:'xl'}]},{name:'套餐',item:[{name:'套餐一'},{name:'套餐二'}]},],goodsSpecList:[{id:'19',price:'200.00',stock:'1',difference:'红色,x,套餐一'},{id:'21',price:'250.00',stock:'1',difference:'红色,x,套餐二'},{id:'19',price:'200.00',stock:'1',difference:'红色,xl,套餐一'},{id:'21',price:'250.00',stock:'1',difference:'红色,xl,套餐二'},{id:'22',price:'300.00',stock:'1',difference:'白色,x,套餐一'},{id:'23',price:'350.00',stock:'1',difference:'白色,x,套餐二'},{id:'22',price:'300.00',stock:'1',difference:'白色,xl,套餐一'},{id:'23',price:'350.00',stock:'1',difference:'白色,xl,套餐二'},{id:'24',price:'300.00',stock:'1',difference:'黑色,x,套餐一'},{id:'25',price:'350.00',stock:'1',difference:'黑色,x,套餐二'},{id:'24',price:'300.00',stock:'1',difference:'黑色,xl,套餐一'},{id:'25',price:'350.00',stock:'0',difference:'黑色,xl,套餐二'},],shopItemInfo:{},//准备和选中的值进行匹配的数据selectedAttr:[],//选中的值selectedAttrIndex:[],//是否选中selectSpec:{},//选中的规格};},onLoad(options){//归类规格this.goodsSpecList.forEach(x=>{this.shopItemInfo[x.difference]= x })//给每个规格的选项添加一个checked属性,用来判断是否可以选择选中this.specList.forEach(x=>{ x.item.forEach(y=>{ y.checked =true})})},methods:{/**
         * 点击选择规格
         * @param {*} specItem 选中的具体的规格值
         * @param {*} specItemIndex 选中的具体规格值的索引
         * @param {*} specIndex 选中的规格的索引
         */selectArrtBtn(specItem, specItemIndex, specIndex){//如果数组中没有选中的值,就添加到数组中,有则清空之前选中的值if(this.selectedAttr[specIndex]!= specItem.name){//没有选中项,选中this.selectedAttr[specIndex]= specItem.name
                this.selectedAttrIndex[specIndex]= specItemIndex
            }else{//如果已经选中了,就代表是取消选择this.selectedAttr[specIndex]=''this.selectedAttrIndex[specIndex]=-1}this.check()this.selectSpec =this.shopItemInfo[this.selectedAttr.join(',')]},check(){//检查let specList =this.specList
            //定义一个存储被选中的值let result =[]for(let i in specList){
                result[i]=this.selectedAttr[i]?this.selectedAttr[i]:''//获取已经选中的规格对,没有的部分填充空白}for(let i in specList){let last = result[i]for(let k in specList[i].item){
                    result[i]= specList[i].item[k].name
                    specList[i].item[k].checked =this.isMay(result)}
                result[i]= last
            }this.specList = specList
        },//判断是否被选中isMay(result){for(let i in result){//如果有一个为空,就返回trueif(result[i]==''){returntrue}}let shopItem =this.shopItemInfo[result.join(',')]if(this.shopItemInfo[result.join(',')]){//存在return shopItem.stock !=0}else{//不存在returnfalse}}}}</script>

四、解释

只对js部分的代码进行解释,其余代码比较简单

初始化

onLoad(options){//归类规格this.goodsSpecList.forEach(x=>{this.shopItemInfo[x.difference]= x })//给每个规格的选项添加一个checked属性,用来判断是否可以选择选中this.specList.forEach(x=>{ x.item.forEach(y=>{ y.checked =true})})},

判断是否已经选中了,如果选中了就清楚选中的结果,如果没有选中,就选中点击项

selectArrtBtn(specItem, specItemIndex, specIndex){// 1 如果数组中没有选中的值,就添加到数组中,有则清空之前选中的值if(this.selectedAttr[specIndex]!= specItem.name){//没有选中项,选中this.selectedAttr[specIndex]= specItem.name
        this.selectedAttrIndex[specIndex]= specItemIndex
    }else{//如果已经选中了,就代表是取消选择this.selectedAttr[specIndex]=''this.selectedAttrIndex[specIndex]=-1}//this.check()//****重点this.selectSpec =this.shopItemInfo[this.selectedAttr.join(',')]//***把该项作为选中项},

check函数是重点函数。所有的处理都在这个函数里面

check(){//检查let specList =this.specList//初始化一个数组,方便调用let result =[]//定义一个存储被选中的值//获取已经选中的规格对,没有的部分填充空白。例如:选择了白色 =>['白色','','']for(let i in specList){
        result[i]=this.selectedAttr[i]?this.selectedAttr[i]:''}for(let i in specList){let last = result[i]for(let k in specList[i].item){//每次遍历会i会加1,例如//拼接具体的规格名字
            result[i]= specList[i].item[k].name
            specList[i].item[k].checked =this.isMay(result)}
        result[i]= last
    }this.specList = specList
},
从for (let i in specList)开始
    
选择一个的情况
开始时的result:['白色','','']
    
    第一次外循环,当前外循环的是 { name: '颜色', item: [{ name: '白色' }, { name: '黑色' }, { name: '红色' }] }
        i=0
        备份 last='白色'
        内循环开始,当前内循环的是[{ name: '白色' }, { name: '黑色' }, { name: '红色' }] }
    
        第一次内循环
        i=0;k=0
        specList[0].item[0]=>{ name: '白色' }
        result[0]=specList[0].item[0].name     => result:['白色','','']        
        specList[0].item[0].checked = this.isMay(result)=>{ name: '白色' ,checked:true}=>{ name: '白色' ,checked:true}
        
        第二次内循环
        i=0;k=1
        specList[0].item[0]=>{ name: '黑色' }
        result[0]=specList[0].item[1].name     => result:['白色','','']        
        specList[0].item[1].checked = this.isMay(result)=>{ name: '黑色' ,checked:true}=>{ name: '黑色' ,checked:true}
        
        第三次内循环
        i=0;k=2
        specList[0].item[0]=>{ name: '红色' }
        result[0]=specList[0].item[2].name     => result:['红色','','']        
        specList[0].item[2].checked = this.isMay(result)=>{ name: '红色' ,checked:true}=>{ name: '红色' ,checked:true}
        
        内循环结束
        重新给result[i]赋值,重新赋值后的result['白色','','']

    第二次外循环,当前外循环的是{ name: '尺码', item: [{ name: 'x' }, { name: 'xl' }] }
        i=1;result=>['白色','','']
        备份 last=result[1] =>last:''
        内循环开始,当前内循环的是[{ name: 'x' }, { name: 'xl' }]

        第一次内循环
        i=1;k=0
        specList[1].item[0]=>{ name: 'x' }
        result[1]=specList[1].item[0].name     => result:['白色','x','']
        specList[1].item[0].checked = this.isMay(result)=>{ name: 'x' ,checked:true}=>{ name: 'x' ,checked:true}
        
        第二次内循环
        i=1;k=1
        specList[1].item[1]=>{ name: 'xl' }
        result[1]=specList[1].item[1].name     => result:['白色','x','']
        specList[1].item[1].checked = this.isMay(result)=>{ name: 'xl' ,checked:true}=>{ name: 'xl' ,checked:true}
        
        内循环结束
        重新给result[i]赋值,重新赋值后的result['白色','','']
        
    第三次外循环,当前外循环的是{ name: '套餐', item: [{ name: '套餐一' }, { name: '套餐二' }] }
        i=2;result=>['白色','','']
        备份 last=result[2] =>last:''
        内循环开始,当前内循环的是[{ name: '套餐一' }, { name: '套餐二' }]
        第一次内循环
        i=2;k=0
        specList[2].item[0]=>{ name: '套餐一' }
        result[2]=specList[2].item[0].name     => result:['白色','','套餐一']
        specList[2].item[0].checked = this.isMay(result)=>{ name: '套餐一' ,checked:true}=>{ name: '套餐一' ,checked:true}
        
        第二次内循环
        i=2;k=1
        specList[2].item[1]=>{ name: '套餐二' }
        result[2]=specList[1].item[1].name     => result:['白色','','套餐二']
        specList[2].item[1].checked = this.isMay(result)=>{ name: '套餐二' ,checked:true}=>{ name: '套餐二' ,checked:true}

选择两个的情况
开始时的result:['白色','xl','']
    前两次的外循环和上面的情况一至,只接收第三次外循环时的情况
    第三次外循环,当前外循环的是{ name: '套餐', item: [{ name: '套餐一' }, { name: '套餐二' }] }
        i=2
        备份 last=''
        内循环开始,当前内循环的是[{ name: '套餐一' }, { name: '套餐二' }]
        第一次内循环
        i=2;k=0
        specList[2].item[0]=>{ name: '套餐一' }
        result[2]=specList[2].item[0].name     => result:['白色','xl','套餐一']
        specList[2].item[0].checked = this.isMay(result)
        
        第二次内循环
        i=2;k=1
        specList[2].item[1]=>{ name: '套餐二' }
        result[2]=specList[1].item[1].name     => result:['白色','xl','套餐二']
        specList[2].item[1].checked = this.isMay(result)    


这里引出isMay函数的逻辑

isMay(result){for(let i in result){//如果有一个为空,就返回trueif(result[i]==''){returntrue}}let shopItem =this.shopItemInfo[result.join(',')]if(this.shopItemInfo[result.join(',')]){//存在return shopItem.stock !=0}else{//不存在returnfalse}}
判断传进来的result是否有项是空的。如果有代表不是完成的选择,返回true继续选择
如果没有空项,那么代表选择是一个完成的规格信息,开始做库存等的判断。
标签: javascript

本文转载自: https://blog.csdn.net/weixin_45497567/article/details/137117399
版权归原作者 何必何必何必 所有, 如有侵权,请联系我们删除。

“前端商品SKU的选择”的评论:

还没有评论