ICode9

精准搜索请尝试: 精确搜索
首页 > 其他分享> 文章详细

vue3项目-小兔鲜儿笔记-商品详情页02

2022-09-06 00:03:05  阅读:203  来源: 互联网

标签:02 sku const 鲜儿 value 详情页 key 按钮 specs


1. SKU和SPU概念

SPU代表一个商品,这个商品可以拥有很多属性

SKU代表这个商品可选规格的任意组合,是库存单位唯一标识

 

2. 路径字典

大致步骤

  1. 根据后台返回的sku数据得到有效sku组合(inventory > 0)

  2. 处理sku数组,使用power-set算法得到sku数组的子集

    • 比如:['蓝色', '中国'] => ['蓝色'], ['中国'], ['蓝色', '中国']

  3. 将子集内容作为key,对应查找到的skuId作为value存入路径对象中

    • 比如:['蓝色','中国'] => '蓝色☆中国': 1238978971

import bwPowerSet from '@/vender/power-set'

const spliter = '★'
const pathMap = {}

export const usePathMap = (skus) => {
  skus.forEach((sku) => {
    if (sku.inventory > 0) {
      // 3.处理skus数组,参考例子:['蓝色','中国'] => ['蓝色'], ['中国'], ['蓝色','中国']
      // 3.1 要先处理skus数组为上面例子的形式,将属性名映射成数组
      const valueArr = sku.specs.map((value) => value.valueName)
      // 3.2 使用power-set算法得到skus数组的子集
      const valuePowerSet = bwPowerSet(valueArr)
      // 4.1 处理子集的形式,把数组映射成字符串得到key值
      valuePowerSet.forEach((arr) => {
        const key = arr.join(spliter)
        // 4.2 把key和skuId作为key-value存储到路径字典
        // 4.2.1 如果pathMap[key]已存在,则继续Push skuID
        // 4.2.2 如果pathMap[key]不存在,则设置成数组
        if (key !== '') {
          if (pathMap[key]) {
            pathMap[key].push(sku.id)
          } else {
            pathMap[key] = [sku.id]
          }
        }
      })
    }
  })

  return pathMap
}

 

3. 规格组件的选中效果

大致步骤

  1. // 关键数据:goods.specs = [spec, spec, spec]

    // spec = {name: '颜色', values: [{valueName: '黑色'}, {valueName: '蓝色'}]}

    // 选中和禁用的状态:selected和disabled,这两个状态都是加到每个按钮上的

  2. 绑定按钮点击事件,完成选中和取消选中

    • 当前点的是选中,取反

    • 当前点的是未选中,先遍历当前规格的所有按钮,全部取消选中,再当前按钮选中。

const changeSku = (goods, specs, spec, value) => {
  if (value.disabled) return
  if (value.selected) {
    value.selected = false
  } else {
    spec.values.forEach((val) => {
      if (val.name !== value.name) {
        val.selected = false
      }
    })
    value.selected = true
    。。。
}

 

4. 规格组件-按钮禁用状态

目的:在组件初始化的时候,以及点击规格中按钮的时候,去更新其他按钮的禁用状态

  1. 获取当前选中的值的数组:['黑色', undefined, undefined]

  2. 遍历按钮:先遍历每一种规格,取出当前选中的值的数组:['黑色', undefined, undefined],再遍历每一个按钮

    • 如果这个按钮已经选中,忽略判断禁用状态

    • 如果这个按钮没被选中,则拿着这个按钮的值按顺序去套入,得到套入后的数组,过滤掉undefined,加入☆拼接成key,比如:蓝色☆中国,拿这个key去路径字典中查找,没有查找到就设置这个按钮为禁用状态

// 获取规格参数数组,参考数据:如果点击了蓝色,其他未点 => ['蓝色', undefined, undefined]
export const getSelectedArr = (specs) => {
  const selectedArr = []
  specs.forEach((spec) => {
    const selectedVal = spec.values.find((val) => val.selected)
    selectedArr.push(selectedVal ? selectedVal.name : undefined)
  })

  return selectedArr
}
// 更新按钮的禁用状态
export const updateDisable = (specs, pathMap) => {
  // 先遍历每一种规格,取出当前选中的值的数组
  specs.forEach((spec, i) => {
    const selectedArr = getSelectedArr(specs)
    // 再遍历规格中的每一个按钮,拿按钮的值按顺序套入
    spec.values.forEach((val) => {
      if (val.name !== selectedArr[i]) {
        selectedArr[i] = val.name
        // 去除undefined得到key值,到路径字典查找是否有该key,无则设置该按钮disabled为true
        const key = selectedArr.filter((item) => item).join(spliter)
        val.disabled = pathMap[key] ? false : true
      }
    })
  })
}
const changeSku = (goods, specs, spec, value) => {
  if (value.disabled) return
  if (value.selected) {
    value.selected = false
  } else {
    spec.values.forEach((val) => {
      if (val.name !== value.name) {
        val.selected = false
      }
    })
    value.selected = true
    // 点击按钮时更新按钮的禁用状态
    updateDisable(specs, pathMap)
    // 当选择了完整的sku之后,触发change事件让父组件收到更新的sku
    const validSelectedArr = getSelectedArr(specs).filter((v) => v)
    if (validSelectedArr.length === specs.length) {
      // 完整的sku
      const key = validSelectedArr.join('★')
      const skuIds = pathMap[key]
      const sku = goods.skus.find((sku) => sku.id === skuIds[0])
      emit('change', {
        skuId: sku.id,
        price: sku.price,
        oldPrice: sku.oldPrice,
        inventory: sku.inventory,
        specsText: sku.specs
          .reduce((p, c) => `${p} ${c.name}:${c.valueName}`, '')
          .trim()
      })
    } else {
      emit('change', {})
    }
  }
}
父组件:
// 监听sku组件的自定义事件,拿到更新的sku
const changeSku = (sku) => {
  console.log(sku)
  // 用更新的sku去修改goods的现价和原价还有库存
  goods.value.price = sku.price
  goods.value.oldPrice = sku.oldPrice
  goods.value.inventory = sku.inventory
}
// 组件初始化的时候根据传来的skuid默认选中按钮
export const initSelected = (goods, skuId) => {
  const sku = goods.skus.find((sku) => sku.id === skuId)
  // 根据sku中的spec描述信息,遍历specs数组,找到对应的按钮并选中
  if (sku) {
    goods.specs.forEach((spec, i) => {
      // 找到sku描述的规格名
      if (spec.name === sku.specs[i].name) {
        spec.values.forEach((value) => {
          // 找到sku描述的属性名
          if (value.name === sku.specs[i].valueName) {
            value.selected = true
          }
        })
      }
    })
  }
}

 

标签:02,sku,const,鲜儿,value,详情页,key,按钮,specs
来源: https://www.cnblogs.com/jzhFlash/p/16660129.html

本站声明: 1. iCode9 技术分享网(下文简称本站)提供的所有内容,仅供技术学习、探讨和分享;
2. 关于本站的所有留言、评论、转载及引用,纯属内容发起人的个人观点,与本站观点和立场无关;
3. 关于本站的所有言论和文字,纯属内容发起人的个人观点,与本站观点和立场无关;
4. 本站文章均是网友提供,不完全保证技术分享内容的完整性、准确性、时效性、风险性和版权归属;如您发现该文章侵犯了您的权益,可联系我们第一时间进行删除;
5. 本站为非盈利性的个人网站,所有内容不会用来进行牟利,也不会利用任何形式的广告来间接获益,纯粹是为了广大技术爱好者提供技术内容和技术思想的分享性交流网站。

专注分享技术,共同学习,共同进步。侵权联系[81616952@qq.com]

Copyright (C)ICode9.com, All Rights Reserved.

ICode9版权所有