前言

做电商项目呢,离不开多规格商品,SKU 也是弄了许久才搞出来,主要是多层级的联动关系,用ID和库存来判断是否是按钮禁止状态

下面就放下代码:

以封装的小程序为例:

WXML:

<view class="sku-box" wx:if="{{cpSkuTree.length}}">
<view class="sku-row" wx:for="{{cpSkuTree}}" wx:key="{{index}}">
<view class="sku-title">{{item.k}}</view>
<view class="sku-wrap flex-row">
<view class="sku-item {{iitem.disabled ? 'disabled': ''}} {{iitem.selected ? 'selected': ''}}" wx:for="{{item.v}}" wx:for-item="iitem" wx:for-index="iindex" wx:key="{{iindex}}" data-index="{{index}}" data-iindex="{{iindex}}" data-k="{{item}}" data-value="{{iitem}}" catchtap="selectSku">{{iitem.name}}</view>
</view>
</view>
</view>

JS:

const computedBehavior = require('miniprogram-computed')

Component({
behaviors: [computedBehavior],
properties: {
skuTree: {
type: Array,
value: [],
observer: function (newVal) {
let cpNewVal = JSON.parse(JSON.stringify(newVal))
cpNewVal.forEach( row => {
row.v.forEach(item => {
Object.assign(item, {
selected: false,
disabled: false
})
})
})
this.setData({
cpSkuTree: cpNewVal
})
this.judgeAllItem()
}
},
skuList: {
type: Array,
value: []
}
},
data: {
cpSkuTree: [],
// 选择的 sku 组合
selectedSku: {
}
},
computed: { },
methods: {
// 点击sku按钮
selectSku (e) {
const k = e.currentTarget.dataset.k
const index = e.currentTarget.dataset.index
const value = e.currentTarget.dataset.value
const iindex = e.currentTarget.dataset.iindex
value.disabled = true
if (this.data.cpSkuTree[index].v[iindex].disabled) {
return
}
// 勾选或者反选
const key = `selectedSku.${k.ks}`
if (!this.data.cpSkuTree[index].v[iindex].selected) {
// 勾选把值记住
this.setData({
[key]: value.id
})
} else {
// 反选把值删掉
this.setData({
[key]: ''
})
}
this.setData({
[`cpSkuTree[${index}].v[${iindex}].selected`]: !this.data.cpSkuTree[index].v[iindex].selected
})
this.cancelOption(index, value)
this.judgeAllItem()
this.changePic(index, iindex)
if (this.isAllSelected()) {
const skuData = this.getSkuComb()
this.triggerEvent('selectChange', skuData)
} else {
this.triggerEvent('selectChange', null)
}
},
/**
* 取消同一组所有选项
*/
cancelOption (index, value) {
let rowList = this.data.cpSkuTree[index].v
for (let i = 0; i < rowList.length; i++) {
if (rowList[i].id != value.id) {
this.setData({
[`cpSkuTree[${index}].v[${i}].selected`]: false
})
}
}
},
/**
* 循环判断是否可选
*/
judgeAllItem () {
let tree = this.data.cpSkuTree
for (let i = 0; i < tree.length; i++) {
let v = tree[i].v
for (let j = 0; j < v.length; j++) {
if (this.isSkuChoosable(tree[i].ks, v[j].id)) {
this.setData({
[`cpSkuTree[${i}].v[${j}].disabled`]: false
})
} else {
this.setData({
[`cpSkuTree[${i}].v[${j}].disabled`]: true
})
}
}
}
this.getSelectedText()
},
/**
* 判断可选项的库存
*/
isSkuChoosable (ks, id) {
const list = this.data.skuList
const selectedSku = this.data.selectedSku
// 先假设已经选中剩余按钮
let matchedSku = Object.assign({}, selectedSku, {
[ks]: id
}) // 将matchedSku中有效的key提取
let skusToCheck = Object.keys(matchedSku).filter(
skuKey => matchedSku[skuKey] != ''
)
// 有效key值匹配有多少sku
let filterSku = list.filter(sku =>
skusToCheck.every(
skuKey => matchedSku[skuKey] == sku[skuKey]
)
)
// 假设按钮包含所有sku的库存数
let stock = filterSku.reduce((total, sku) => {
total += sku.stock_num
return total
}, 0)
return stock > 0 },
/**
* 判断是否选完所有规格
*/
isAllSelected () {
let selectedSku = this.data.selectedSku
let selected = Object.keys(selectedSku).filter(
skuKey => selectedSku[skuKey] !== ''
)
return selected.length === this.data.cpSkuTree.length
},
/**
* 获得已经确定的组合
*/
getSkuComb () {
let selectedSku = this.data.selectedSku
let list = this.data.skuList
let skusToCheck = []
this.data.cpSkuTree.forEach(item => {
skusToCheck.push(item.ks)
})
let filteredSku = list.filter(sku => (
skusToCheck.every(skuKey => selectedSku[skuKey] == sku[skuKey])
)
)
return filteredSku[0]
},
/**
* 修改图片
*/
changePic (index, iindex) {
if (index == 0) {
this.triggerEvent('changePic', this.data.cpSkuTree[index].v[iindex].picUrl)
}
},
// 选择属性文字
getSelectedText () {
let selectedSku = this.data.selectedSku
let text = ''
Object.keys(selectedSku).forEach(skuKey => {
const id = selectedSku[skuKey]
const tree = this.data.cpSkuTree
for (let i = 0; i < tree.length; i++) {
const v = tree[i].v
for (let j = 0; j < v.length; j++) {
if (v[j].id == id) {
text = `${text} ${v[j].name}`
}
}
}
})
this.triggerEvent('textChange', text)
}
}
})

上面都有注释:

CSS

.flex-row {
display: flex;
flex-direction: row;
} .flex-col {
display: flex;
flex-direction: column;
}
.sku-box {
width: 100%;
background: #fff;
padding: 40rpx;
}
.sku-row {
margin-bottom: 36rpx;
}
.sku-title {
color: #333;
font-size: 24rpx;
line-height:;
}
.sku-wrap {
margin-top: 36rpx;
flex-wrap: wrap;
}
.sku-item {
min-width: 160rpx;
padding: 18rpx 14rpx;
color: #555555;
font-size: 24rpx;
line-height:;
border-radius: 4rpx;
background: #EAEAEA;
border: 1rpx solid #EAEAEA;
text-align: center;
margin-bottom: 20rpx;
}
.sku-item+.sku-item {
margin-left: 24rpx;
}
.sku-item.disabled {
color: #ababab;
}
.sku-item.selected {
color: #38ADFF;
background:rgba(56,173,255,0.1);
border: 1rpx solid #38ADFF;
}

然后封装使用在 父组件使用,

这个就是效果图,

嘻嘻 这样就算封装完毕

多规格商品SKU 组件封装的更多相关文章

  1. 商品sku规格选择效果,没有商品的不能选中,选择顺序不影响展示结果

    <!DOCTYPE HTML> <html lang="en-US"> <head> <meta charset="UTF-8& ...

  2. vue+element 实现商品sku效果

    在网上搜索了很久,没有发现合适sku编辑的文章,只能自己写一个vue+element 的sku编辑功能.实现的效果如下图 除成本.售价.库存.货号这几个写死的属性外,可自行添加/删除商品属性,自行添加 ...

  3. jquery实现商品sku多属性选择(商品详情页)

    转载于https://blog.csdn.net/csdn924618338/article/details/51455595 实现效果 源码 <!DOCTYPE HTML> <ht ...

  4. 循序渐进VUE+Element 前端应用开发(20)--- 使用组件封装简化界面代码

    VUE+Element 前端应用,比较不错的一点就是界面组件化,我们可以根据重用的指导方针,把界面内容拆分为各个不同的组合,每一个模块可以是一个组件,也可以是多个组件的综合体,而且这一个过程非常方便. ...

  5. B2C电子商务系统研发——商品SKU分析和设计(二)

    转:http://www.cnblogs.com/winstonyan/archive/2012/01/07/2315886.html 上文谈到5种商品SKU设计模式,本文将做些细化说明. 笔者研究过 ...

  6. Vuejs 页面的区域化与组件封装

    组件的好处 当我用vue写页面的时候,大量的数据页面渲染,引入组件简化主页面的代码量,当代码区域块代码差不多相同时,组件封装会更加简化代码.组件是Vue.js最强大的功能之一. 组件可以扩展HTML元 ...

  7. ReactNative之从HelloWorld中看环境搭建、组件封装、Props及State

    开篇呢,先给大家问个好,今天是中秋节,祝大家中秋节快乐!!虽然是中秋节,但是木有回家还是总结一下知识点写写博客吧,想着昨天总结一下的,但是昨天和几个同学小聚了一下,酒逢知己总是千杯少呢,喝的微醺不适合 ...

  8. Vue + Element UI 实现权限管理系统 (功能组件封装)

    组件封装 为了避免组件代码的臃肿,这里对主要的功能部件进行封装,保证代码的模块化和简洁度. 组件结构 组件封装重构后,试图组件结构如下图所示 代码一览 Home组件被简化,包含导航.头部和主内容三个组 ...

  9. Vue + Element UI 实现权限管理系统 前端篇(七):功能组件封装

    组件封装 为了避免组件代码的臃肿,这里对主要的功能部件进行封装,保证代码的模块化和简洁度. 组件结构 组件封装重构后,试图组件结构如下图所示 代码一览 Home组件被简化,包含导航.头部和主内容三个组 ...

随机推荐

  1. Hadoop集群搭建-02安装配置Zookeeper

    Hadoop集群搭建-05安装配置YARN Hadoop集群搭建-04安装配置HDFS  Hadoop集群搭建-03编译安装hadoop Hadoop集群搭建-02安装配置Zookeeper Hado ...

  2. Android控制UI界面

    ⒈使用XML布局文件控制UI界面[推荐] Android推荐使用XML布局文件来控制视图,这样不仅简单.明了,而且可以将应用的视图控制逻辑从Java或Kotlin代码中分离出来,放入XML文件中控制, ...

  3. Web安全微专业正式课 大纲(图片)

    如果想报名学习,可以联系我.QQ:1097321785.

  4. C++字符转换等常用方法

    下面是C++中字符编码格式转换(包括ANSI转换为UTF8,UTF8转换为ANSI,ANSI转换为unicode,unicode转换为ANSI,UTF8转换为unicode,unicode转换为UTF ...

  5. 树莓派和STM32通过USB和串口通信记录

    不管怎样,为了简便开发,通信选择串口通信. 推荐文章:https://blog.csdn.net/magnetoooo/article/details/53564797 推荐测试工具:https:// ...

  6. python 小数精度控制

    可以用:round(数值,保留小数位数) 详情参考 https://www.cnblogs.com/herbert/p/3402245.html

  7. cpu 100%怎样定位

    先用top定位最耗cpu的java进程 例如: 12430工具:top或者 htop(高级)方法:top -c 显示进程运行详细列表键入 P (大写P),按照cpu进行排序 然后用top -p 124 ...

  8. centos7 开放/关闭防火墙和端口

    --------------------------------------------------------------防火墙----------------------------------- ...

  9. hadoop-hive的内表和外表

    --创建内表create table if not exists employee(id int comment 'empoyeeid',dateincompany string comment 'd ...

  10. web项目部署在centos 7验证码显示不出来解决方案

    今天把项目部署在centos7上,发现验证码显示不出来,看了一下tomcat日志 Exception in thread "http-nio-8080-exec-3" java.l ...