前端sku實現(商城中商品規格選擇)


轉自簡書  https://www.jianshu.com/p/0376aa6e648e

一、 效果圖

 

 

 


 


 

 

 

1、 先看數據 (這里是全數據 雖然有點長但是方便調試 測試)

    const specList = [ { title: "顏色", list: ["紅色", "紫色", "白色", "黑色"] }, { title: "套餐", list: ["套餐一", "套餐二", "套餐三", "套餐四"] }, { title: "內存", list: ["64G", "128G", "256G"] } ] const skuList = [ // { id: 1608188117177, specs: ["紅色", "套餐一", "64G"] }, { id: 1608188117178, specs: ["紅色", "套餐一", "128G"] }, { id: 1608188117179, specs: ["紅色", "套餐一", "256G"] }, { id: 1608188117180, specs: ["紅色", "套餐二", "64G"] }, { id: 1608188117181, specs: ["紅色", "套餐二", "128G"] }, { id: 1608188117182, specs: ["紅色", "套餐二", "256G"] }, { id: 1608188117183, specs: ["紅色", "套餐三", "64G"] }, { id: 1608188117184, specs: ["紅色", "套餐三", "128G"] }, { id: 1608188117185, specs: ["紅色", "套餐三", "256G"] }, // { id: 1608188117186, specs: ["紅色", "套餐四", "64G"] }, // { id: 1608188117187, specs: ["紅色", "套餐四", "128G"] }, // { id: 1608188117188, specs: ["紅色", "套餐四", "256G"] }, // { id: 1608188117189, specs: ["紫色", "套餐一", "64G"] }, // { id: 1608188117190, specs: ["紫色", "套餐一", "128G"] }, // { id: 1608188117191, specs: ["紫色", "套餐一", "256G"] }, { id: 1608188117192, specs: ["紫色", "套餐二", "64G"] }, { id: 1608188117193, specs: ["紫色", "套餐二", "128G"] }, { id: 1608188117194, specs: ["紫色", "套餐二", "256G"] }, { id: 1608188117195, specs: ["紫色", "套餐三", "64G"] }, { id: 1608188117196, specs: ["紫色", "套餐三", "128G"] }, { id: 1608188117197, specs: ["紫色", "套餐三", "256G"] }, { id: 1608188117198, specs: ["紫色", "套餐四", "64G"] }, { id: 1608188117199, specs: ["紫色", "套餐四", "128G"] }, { id: 1608188117200, specs: ["紫色", "套餐四", "256G"] }, { id: 1608188117201, specs: ["白色", "套餐一", "64G"] }, { id: 1608188117202, specs: ["白色", "套餐一", "128G"] }, { id: 1608188117203, specs: ["白色", "套餐一", "256G"] }, { id: 1608188117204, specs: ["白色", "套餐二", "64G"] }, // { id: 1608188117205, specs: ["白色", "套餐二", "128G"] }, // { id: 1608188117206, specs: ["白色", "套餐二", "256G"] }, // { id: 1608188117207, specs: ["白色", "套餐三", "64G"] }, // { id: 1608188117208, specs: ["白色", "套餐三", "128G"] }, // { id: 1608188117209, specs: ["白色", "套餐三", "256G"] }, // { id: 1608188117210, specs: ["白色", "套餐四", "64G"] }, { id: 1608188117211, specs: ["白色", "套餐四", "128G"] }, { id: 1608188117212, specs: ["白色", "套餐四", "256G"] }, { id: 1608188117213, specs: ["黑色", "套餐一", "64G"] }, { id: 1608188117214, specs: ["黑色", "套餐一", "128G"] }, { id: 1608188117215, specs: ["黑色", "套餐一", "256G"] }, { id: 1608188117216, specs: ["黑色", "套餐二", "64G"] }, // { id: 1608188117217, specs: ["黑色", "套餐二", "128G"] }, // { id: 1608188117218, specs: ["黑色", "套餐二", "256G"] }, // { id: 1608188117219, specs: ["黑色", "套餐三", "64G"] }, // { id: 1608188117220, specs: ["黑色", "套餐三", "128G"] }, // { id: 1608188117221, specs: ["黑色", "套餐三", "256G"] }, // { id: 1608188117222, specs: ["黑色", "套餐四", "64G"] }, { id: 1608188117223, specs: ["黑色", "套餐四", "128G"] }, { id: 1608188117224, specs: ["黑色", "套餐四", "256G"] } ] 

2、 頁面代碼

<div id="app"> <h3>前端SKU實現</h3> <div v-for="(item,index) in specList" :key="index"> <div class='title'>{{item.title}}</div> <div class='spec'> <div class='spec-item' v-for="(its,ins) in item.list" :key="its.name + ins"> <span @click="changeSpec(item.title, its.name, its.able)" :class="[selectSpec[item.title] === its.name ? 'active' : '' , its.able? '' : 'disabled']">{{its.name}}</span> </div> </div> </div> </div> <style> .spec-item{ display: inline-block; margin-right: 10px; } .spec-item span { border:1px solid #eee; cursor: pointer; padding:5px 10px; } .spec-item .active{ border: 1px solid red; background-color: red; color:#fff; } .spec-item .disabled{ color: #c0c4cc; cursor: not-allowed; background-image: none; background-color: #fff; border-color: #ebeef5; } </style> 

3、 核心JS邏輯

// 第一步引入數據 這里引入的數據就是上面的 specList skuList import {specList, skuList} from './data' export default { name: 'App', data() { return { specList:[], skuList:[], selectSpec:{}, // 選擇數據的對象 將已選的數據放在這個對象里面記錄下來 用對象的好處在下面深拷貝處就能體驗到了 } }, created() { // 第二步 處理數據 this.skuList = skuList; // 初始化選擇數據的對象 specList.forEach(item => { this.$set(this.selectSpec, item.title, ""); }) // 將規格數據處理成我們視圖所需要的數據類型 this.specList = specList.map(item => { return { title:item.title, list: item.list.map(its => { return { name:its, // 判斷是否可以選擇 // 這里相當於init 初始化數據 this.isAble() 核心判斷邏輯 able: this.isAble(item.title, its) // 注釋的調試看邏輯代碼 false } }) } }) // 注釋的調試看邏輯代碼 // this.selectSpec = { // '顏色':'', // '套餐':'套餐一', // '內存':'64G' // } // this.isAble('顏色', '紅色') }, methods:{ // 核心判斷邏輯 // 判斷規格是否可以被選擇 核心函數 key當前的規格的title value規格值 isAble(key, value){ // 深拷貝 避免被影響 var copySelectSpec = JSON.parse(JSON.stringify(this.selectSpec)); // 用對象的好處就在這了 直接賦值當前驗證項 copySelectSpec[key] = value; // 用數組的 some 方法 效率高 符合條件直接退出循環 let flag = this.skuList.some(item => { // 條件判斷 核心邏輯判斷 // console.log(item) var i = 0 ; // 這個for in 循環的邏輯就對底子不深的人來說就看不懂了 原理就是循環已經選中的 和 正在當前對比的數據 和 所有的sku對比 只有當前驗證的所有項滿足sku中的規格或者其他規格為空時 即滿足條件 稍微有點復雜 把注釋的調試代碼打開就調試下就可以看懂了 for(let k in copySelectSpec) { // console.log(copySelectSpec[k]) // 注釋的調試看邏輯代碼 if(copySelectSpec[k] != "" && item.specs.includes(copySelectSpec[k])){ // console.log(item) i++ }else if (copySelectSpec[k] == "") { i++; } } // 符合下面條件就退出了 不符合會一直循環知道循環結束沒有符合的條件就 return false 了 // console.log(i) // 注釋的調試看邏輯代碼 return i == specList.length }) console.log(flag) return flag }, // 點擊事件 changeSpec(key,value,able){ if(!able) return if(this.selectSpec[key] === value){ this.selectSpec[key] = '' }else { this.selectSpec[key] = value } // forEach循環改變原數組 this.specList.forEach(item => { item.list.forEach(its => { its.able = this.isAble(item.title, its.name); console.log(its.name, its.able); }); }); } }, } 
 

鏈接:https://www.jianshu.com/p/0376aa6e648e


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM