小兔鲜儿 - SKU 模块
学会使用插件市场,下载并使用 SKU
组件,实现商品详情页规格展示和交互。
存货单位(SKU)
SKU 概念
存货单位(Stock Keeping Unit),库存管理的最小可用单元,通常称为“单品”。
SKU
常见于电商领域,对于前端工程师而言,更多关注 SKU 算法 和 用户交互体验。
插件市场
uni-app 插件市场,是 uni-app 官方插件生态集中地。
SKU
属于电商常见业务,插件市场有现成的 SKU
插件,我们下载并在项目中使用。

下载 SKU 插件
经过综合评估,我们选择该SKU 插件,请下载插件到本地。
体验地址

::: tip 常见问题
Q:如何评估第三方插件的质量?
A:查看插件的评分、评价、下载量、更新频率以及文档完整性,以确保插件具有良好的社区口碑、兼容性、性能和维护状况。
:::
使用 SKU 插件
组件安装到自己项目
- 复制
vk-data-goods-sku-popup
和 vk-data-input-number-box
到项目的根 components
目录下。
- 复制例子代码并运行体验。
插件文档(部分)
Props 参数
Props |
说明 |
类型 |
默认值 |
可选值 |
v-model |
双向绑定,true 为打开组件,false 为关闭组件 |
Boolean |
false |
true、false |
mode |
模式 1:都显示 2:只显示购物车 3:只显示立即购买 |
Number |
1 |
1、2、3 |
localdata |
商品信息本地数据源 |
Object |
- |
- |
Event 事件名
Event |
说明 |
回调参数 |
add-cart |
点击添加到购物车时(需选择完 SKU 才会触发) |
selectShop:当前选择的 sku 数据 |
buy-now |
点击立即购买时(需选择完 SKU 才会触发) |
selectShop:当前选择的 sku 数据 |
open |
打开组件时 |
- |
close |
关闭组件时 |
- |
::: tip 常见问题
Q:为什么插件使用时无需导入?
A:pages.json
的 easycom
配置中,默认自动扫描 xxx/xxx.vue
格式的组件,实现自动导入。
Q:为什么组件代码 Git 提交时报错?
A:插件未采用 eslint
校验代码,请在插件源文件中添加 /* eslint-disable */
,禁用 eslint
。
:::
在 vk-data-goods-sku-popup.vue
和 vk-data-input-number-box.vue
组件禁用 eslint
。
{2}1 2 3 4
| <script> /* eslint-disable */ // 省略组件源代码 </script>
|
温馨提示: 插件的作者已合并 eslint-disable
PR ,现在已无需手动添加该注释。
插件类型问题
尽管该插件未采用 TS 开发,但作者提供了详细的插件文档,我们可以依据文档为插件添加 TS 类型声明文件,从而提高项目数据校验的安全性。
类型声明文件
vk-data-goods-sku-popup.d.ts
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 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145
| import { Component } from "@uni-helper/uni-app-types";
export type SkuPopup = Component<SkuPopupProps>;
export type SkuPopupInstanceType = InstanceType<SkuPopup>;
export type SkuPopupProps = { modelValue: boolean; localdata: SkuPopupLocaldata; mode?: 1 | 2 | 3; noStockText?: string; stockText?: string; maskCloseAble?: boolean; borderRadius?: string | number; minBuyNum?: number; maxBuyNum?: number; stepBuyNum?: number; stepStrictly?: boolean; hideStock?: false; theme?: "default" | "red-black" | "black-white" | "coffee" | "green"; amountType?: 1 | 0; customAction?: () => void; showClose?: boolean; closeImage?: string; priceColor?: string; buyNowText?: string; buyNowColor?: string; buyNowBackgroundColor?: string; addCartText?: string; addCartColor?: string; addCartBackgroundColor?: string; goodsThumbBackgroundColor?: string; disableStyle?: object; activedStyle?: object; btnStyle?: object; goodsIdName?: string; skuIdName?: string; skuListName?: string; specListName?: string; stockName?: string; skuArrName?: string; goodsThumbName?: string; selectArr?: string[];
onOpen: () => void; onClose: () => void; onAddCart: (event: SkuPopupEvent) => void; onBuyNow: (event: SkuPopupEvent) => void; };
export type SkuPopupLocaldata = { _id: string; name: string; goods_thumb: string; spec_list: SkuPopupSpecItem[]; sku_list: SkuPopupSkuItem[]; };
export type SkuPopupSpecItem = { name: string; list: { name: string }[]; };
export type SkuPopupSkuItem = { _id: string; goods_id: string; goods_name: string; image: string; price: number; sku_name_arr: string[]; stock: number; };
export type SkuPopupEvent = SkuPopupSkuItem & { buy_num: number; };
declare module "vue" { export interface GlobalComponents { "vk-data-goods-sku-popup": SkuPopup; } }
|
核心业务
渲染商品规格
使用以下两个属性:
localdata
绑定商品 SKU
数据来源
v-model
双向绑定,显示/隐藏组件
注意:后端返回的数据格式和插件所需的格式不一致,我们需要按插件要求进行处理。
{9-24,28,30,35,37}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
| <script setup lang="ts"> import type { SkuPopupLocaldata } from "@/components/vk-data-goods-sku-popup/vk-data-goods-sku-popup";
// 获取商品详情信息 const goods = ref<GoodsResult>(); const getGoodsByIdData = async () => { const res = await getGoodsByIdAPI(query.id); goods.value = res.result; // SKU组件所需格式 localdata.value = { _id: res.result.id, name: res.result.name, goods_thumb: res.result.mainPictures[0], spec_list: res.result.specs.map((v) => ({ name: v.name, list: v.values })), sku_list: res.result.skus.map((v) => ({ _id: v.id, goods_id: res.result.id, goods_name: res.result.name, image: v.picture, price: v.price * 100, // 注意:需要乘以 100 stock: v.inventory, sku_name_arr: v.specs.map((vv) => vv.valueName), })), }; };
// 是否显示SKU组件 const isShowSku = ref(false); // 商品信息 const localdata = ref({} as SkuPopupLocaldata); </script>
<template> <!-- SKU弹窗组件 --> <vk-data-goods-sku-popup v-model="isShowSku" :localdata="localdata" /> <!-- 弹窗测试 --> <button @tap="isShowSku = true">打开 SKU 弹窗</button> </template>
|
打开弹窗交互
SKU 弹窗的按钮有三种形式。
{23-25,29,31,32}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
| <script setup lang="ts"> // 按钮模式 enum SkuMode { Both = 1, Cart = 2, Buy = 3, } const mode = ref<SkuMode>(SkuMode.Cart); // 打开SKU弹窗修改按钮模式 const openSkuPopup = (val: SkuMode) => { // 显示SKU弹窗 isShowSku.value = true; // 修改按钮模式 mode.value = val; }; </script>
<template> <!-- SKU弹窗组件 --> <vk-data-goods-sku-popup v-model="isShowSku" :localdata="localdata" :mode="mode" add-cart-background-color="#FFA868" buy-now-background-color="#27BA9B" />
<!-- 显示两个按钮 --> <view @tap="openSkuPopup(SkuMode.Both)" class="item arrow" >请选择商品规格</view > <!-- 显示一个按钮 --> <view @tap="openSkuPopup(SkuMode.Cart)" class="addcart"> 加入购物车 </view> <view @tap="openSkuPopup(SkuMode.Buy)" class="payment"> 立即购买 </view> </template>
|
渲染被选中的值
通过 ref
获取组件实例。
通过 computed
计算出被选中的值,渲染到界面中。
{3,5-7,18-23,29}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
| <script setup lang="ts"> // SKU组件实例 const skuPopupRef = ref<SkuPopupInstance>(); // 计算被选中的值 const selectArrText = computed(() => { return skuPopupRef.value?.selectArr?.join(" ").trim() || "请选择商品规格"; }); </script>
<template> <!-- SKU弹窗组件 --> <vk-data-goods-sku-popup v-model="isShowSku" :localdata="localdata" :mode="mode" add-cart-background-color="#FFA868" buy-now-background-color="#27BA9B" ref="skuPopupRef" :actived-style="{ color: '#27BA9B', borderColor: '#27BA9B', backgroundColor: '#E9F8F5', }" /> <!-- 操作面板 --> <view class="action"> <view @tap="openSkuPopup(SkuMode.Both)" class="item arrow"> <text class="label">选择</text> <text class="text ellipsis"> {{ selectArrText }} </text> </view> </view> </template>
|
至此,已经完成 SKU
组件的交互,接下来进入到购物车模块,并实现加入购物车功能。