• Vue3实现 SKU 规格


    效果图
    在这里插入图片描述

    1 HTML 基本结构

    1.1 遍历 SKU 规格数据

    <template>
      <div class="productConten">
        <div v-for="(productItem, productIndex) in specifications" :key="productItem.name">
          <div class="productTitle">{{ productItem.name }}</div>
          <ul class="productItem">
            <li
              v-for="(oItem, oIndex) in productItem.item"
              :key="oItem.name"
              @click="selectArrtBtn(oItem, productIndex, oIndex)"
              :class="{ noneActive: !oItem.checked, active: subIndex[productIndex] == oIndex }"
            >
              {{ oItem.name }}
            </li>
          </ul>
        </div>
      </div>
      <div v-if="boxArr.id">
        {{ boxArr.difference + '--' + boxArr.price }}
      </div>
    </template>
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20

    2 编写 css 基本样式

    <style lang="scss" scoped>
    .productConten {
      width: 500px;
      padding: 40px;
      .productTitle {
        font-weight: 500;
        margin: 10px 0;
      }
      .productItem {
        display: flex;
        margin-bottom: 30px;
        li {
          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;
          color: #fff;
          border: 1px solid #c41e3a;
        }
      }
    }
    </style>
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32

    3 js 代码

    <script setup>
    import { onMounted, ref } from 'vue'
    // 规格数据
    const specifications = ref([
      {
        name: '颜色',
        item: [{ name: '白色' }, { name: '黑色' }, { name: '红色' }]
      },
      {
        name: '尺码',
        item: [{ name: 'x' }, { name: 'xl' }]
      }
    ])
    // 商品仓库数据
    const dataList = ref([
      {
        id: '19',
        price: '200.00',
        stock: '19',
        difference: '红色,x'
      },
      {
        id: '20',
        price: '300.00',
        stock: '29',
        difference: '白色,x'
      },
      {
        id: '21',
        price: '300.00',
        stock: '10',
        difference: '黑色,x'
      },
      {
        id: '21',
        price: '300.00',
        stock: '10',
        difference: '黑色,xl'
      },
      {
        id: '24',
        price: '500.00',
        stock: '10',
        difference: '白色,xl'
      }
    ])
    //存放要和选中的值进行匹配的数据
    const shopItemInfo = ref({})
    //存放被选中的值
    const selectArr = ref([])
    //是否选中 因为不确定是多规格还是单规格,所以这里定义数组来判断
    const subIndex = ref([])
    const boxArr = ref({})
    
    onMounted(() => {
      const difference = dataList.value
      const attrList = specifications.value
      // 1 修改数据结构格式,改成键值对的方式,以方便和选中之后的值进行匹配
      for (let i = 0; i < difference.length; i++) {
        shopItemInfo.value[difference[i].difference] = difference[i]
      }
    
      // 2 给每个规格的选项添加一个checked属性,用来判断是否选中
      for (let i = 0; i < attrList.length; i++) {
        for (let j = 0; j < attrList[i].item.length; j++) {
          attrList[i].item[j].checked = true
        }
      }
      specifications.value = attrList
    })
    
    /**
     * 点击选择规格
     * @param {Object} item 规格的值
     * @param {Number} index 规格标题的索引
     * @param {Number} arrtIndex 规格的索引
     * */
    const selectArrtBtn = (item, index, arrtIndex) => {
      // 1 如果数组中没有选中的值,就添加到数组中,有则清空之前选中的值
      if (selectArr.value[index] != item.name) {
        selectArr.value[index] = item.name
        subIndex.value[index] = arrtIndex
      } else {
        selectArr.value[index] = ''
        // 去掉选中的颜色
        subIndex.value[index] = -1
      }
      checkItem()
      // 3 在能选中的值中查找是否有
      const selectObj = shopItemInfo.value[selectArr.value]
      if (selectObj) {
        boxArr.value = selectObj
      }
    }
    const checkItem = () => {
      const arrt = specifications.value
      // 定义数组存储被选中的值
      let result = []
      for (let i in arrt) {
        result[i] = selectArr.value[i] ? selectArr.value[i] : ''
      }
    
      for (let i in arrt) {
        // 把选中的值提取出来
        let last = result[i]
        for (let k in arrt[i].item) {
          result[i] = arrt[i].item[k].name
          arrt[i].item[k].checked = isMay(result)
        }
        // 还原,目的是记录点下去那个值,避免下一次执行循环时被覆盖
        result[i] = last
      }
      specifications.value = arrt
    }
    
    const isMay = (result) => {
      for (let i in result) {
        if (result[i] == '') return true
      }
      return !shopItemInfo.value[result] ? false : shopItemInfo.value[result]?.stock == 0 ? false : true
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44
    • 45
    • 46
    • 47
    • 48
    • 49
    • 50
    • 51
    • 52
    • 53
    • 54
    • 55
    • 56
    • 57
    • 58
    • 59
    • 60
    • 61
    • 62
    • 63
    • 64
    • 65
    • 66
    • 67
    • 68
    • 69
    • 70
    • 71
    • 72
    • 73
    • 74
    • 75
    • 76
    • 77
    • 78
    • 79
    • 80
    • 81
    • 82
    • 83
    • 84
    • 85
    • 86
    • 87
    • 88
    • 89
    • 90
    • 91
    • 92
    • 93
    • 94
    • 95
    • 96
    • 97
    • 98
    • 99
    • 100
    • 101
    • 102
    • 103
    • 104
    • 105
    • 106
    • 107
    • 108
    • 109
    • 110
    • 111
    • 112
    • 113
    • 114
    • 115
    • 116
    • 117
    • 118
    • 119
    • 120
    • 121
  • 相关阅读:
    Ceres 自动求导(AutomaticDerivatives)进阶
    《30天吃掉那只 TensorFlow2.0》 一、TensorFlow的建模流程
    Spring Framework 6.1 正式发布
    第二章:25+ Python 数据操作教程(第二十五节用 PYTHON 和 R 制作祝福圣诞节)持续更新
    使用VNA(Vector Network Analyzer)对S参数进行去嵌(一)
    数据结构实验六 栈和队列的基本操作及应用
    2022年 hust OJ 最新搭建方式
    python 语音识别(百度api)
    【树形权限】树形列表权限互斥选择、el-tree设置禁用等等
    【Linux】内存查看vmstat命令(虚拟内存统计)
  • 原文地址:https://blog.csdn.net/weixin_49431241/article/details/134421114