首页 > 其他分享 >vue3项目-小兔鲜儿笔记-商品详情页02

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

时间:2022-09-05 23:55:59浏览次数:71  
标签: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
From: https://www.cnblogs.com/jzhFlash/p/16660129.html

相关文章

  • Day02超链接标签及应用
    链接标签超链接​从一个页面链接到另一个页面锚链接功能性链接<!DOCTYPEhtml><htmllang="en"><head><metacharset="UTF-8"><title>链接标签学习<......
  • 使用Visual Studio2022写汇编 代码自动高亮
     本贴帮助使用VS2022写汇编的小伙伴实现代码自动高亮 今天汇编课程老师要求在本地PC上配置一个可以写汇编的环境,选择使用VS2022以及下载的MASM搭建环境。按照网上教程......
  • 信息学奥赛一本通 1314:【例3.6】过河卒(Noip2002)
    时间限制:1000ms      内存限制:65536KB提交数:26367   通过数:11410【题目描述】棋盘上A点有一个过河卒,需要走到目标B点。卒行走的规则:可以向下......
  • 2022-9-5
    2022-9-5HWS2022-Re1这题也算复习了一下tea,踩了一下几个做题的坑,希望自己下次做tea的时候可以注意1.注意ida的赋值问题,要了解出题人的代码规范和习惯2.注意sum值的变化......
  • day02
    ##Windows常用快捷键ctrl+e:打开我的电脑ctrl+shift+esc:打开任务管理器       ##基本的Dos命令打开cmd的方式1.开始+系统+命令提示符......
  • 2022 年 9 月水题选做
    20220901SP30919GCDS-Sabbirandgcdproblem思路:显然答案就是不是任意一个数的因数的最小的质数。这个可以在线性筛的时候记录每个数的最小的素因数即可。算法:线性......
  • 【2022-09-05】Django框架(五)
    Django框架(五)定义模型类fromdjango.dbimportmodels#Createyourmodelshere.classUser(models.Model):uid=models.AutoField(primary_key=True,ver......
  • xx技术2023前端开发卷A
    xx技术2023前端开发卷A选择以下哪种情况会导致浏览器报HTTPS证书告警()网站的https安全证书确实已经过期,根据https安全证书签发国际标准,https安全证书颁发不能超过两......
  • 【题解】做题记录(2022.9)
    可能会断断续续的,是因为可能有的时候忘记了写记录9.5今天搞了一天的平衡树,但大部分都是比较基础的操作[SHOI2009]会场预约题目分析:set大法吼啊我们考虑重新定义两个......
  • 洛谷 P1036 [NOIP2002 普及组] 选数(dfs)
    https://www.luogu.com.cn/problem/P1036题目大意:从给定的n个数中选出m个求和,结果是一个素数的情况有多少种?输入43371219输出1这个题目的代码是根据Acwing中......