实战指南)
Vant Coupon 优惠券选择器与兑换列表CouponList实战指南【免费下载链接】vantA lightweight, customizable Vue UI library for mobile web apps.项目地址: https://gitcode.com/GitHub_Trending/va/vant导读CouponList优惠券选择器是 Vant 移动端组件库中用于优惠券兑换与选择的核心组件它和配套的CouponCell优惠券单元格一起构成了电商下单、结算等场景下完整的一站式优惠券交互方案单元格展示当前已选优惠券弹出层内嵌列表完成可用券的勾选与不可用券的展示顶部兑换栏还支持输入兑换码实时兑换新券。阅读完本篇你将掌握CouponCellCouponList的组合用法、全部 Props/Events/Slots 参数语义、CouponInfo数据结构的字段含义以及底层源码的实现原理与主题定制方案。组件介绍与引入优惠券选择器用于优惠券的兑换和选择它通常与优惠券单元格CouponCell配合使用CouponCell负责在页面上以单元格形式展示“已选券/可选券”的金额汇总CouponList则负责在弹层中展示可用券、不可用券两个列表并提供兑换入口。通过以下方式全局注册组件更多注册方式可参考组件注册import { createApp } from vue; import { CouponCell, CouponList } from vant; const app createApp(); app.use(CouponCell); app.use(CouponList);注册后即可在模板中直接使用van-coupon-cell与van-coupon-list标签。两个组件都通过 index.ts 中的withInstall包装导出并同时注册了VanCouponList/VanCouponCell的全局组件类型享受完整的 TypeScript 提示。代码演示基础用法基础用法是一个“单元格 弹层”的组合模式点击van-coupon-cell打开底部弹出层弹出层内渲染van-coupon-list用户勾选券或兑换新券后通过事件回调更新状态并关闭弹层!-- 优惠券单元格 -- van-coupon-cell :couponscoupons :chosen-couponchosenCoupon clickshowList true / !-- 优惠券列表 -- van-popup v-model:showshowList round positionbottom styleheight: 90%; padding-top: 4px; van-coupon-list :couponscoupons :chosen-couponchosenCoupon :disabled-couponsdisabledCoupons changeonChange exchangeonExchange / /van-popupimport { ref } from vue; export default { setup() { const coupon { available: 1, condition: 无门槛\n最多优惠12元, reason: , value: 150, name: 优惠券名称, startAt: 1489104000, endAt: 1514592000, valueDesc: 1.5, unitDesc: 元, }; const coupons ref([coupon]); const showList ref(false); const chosenCoupon ref(-1); const onChange (index) { showList.value false; chosenCoupon.value index; }; const onExchange (code) { coupons.value.push(coupon); }; return { coupons, showList, onChange, onExchange, chosenCoupon, disabledCoupons: [coupon], }; }, };这段示例完整还原了真实业务链路coupons为可用优惠券数组disabledCoupons为不可用优惠券数组两者都传入CouponList组件内部用 Tabs 分成“可使用优惠券”和“不可使用优惠券”两个 Tab 展示chosenCoupon初始为-1表示未选中任何券点击某张券时组件触发change事件并回传选中索引我们在onChange中关闭弹层并同步chosenCoupon在兑换栏输入兑换码后点击“兑换”按钮组件触发exchange事件并回传兑换码业务方可在onExchange中调用真实兑换接口成功后把新券 push 进coupons列表即会实时刷新。多选用法chosenCoupon 传数组从源码看chosenCoupon的类型是number | number[]见 CouponList.tsx。当传入数组时组件进入多选模式点击优惠券时change事件回传的是新的选中索引数组而非单个索引同时点击底部按钮会回传[]清空全部选择而不是-1。这一行为在updateChosenCoupon辅助函数中实现——若索引已在数组中则移除否则追加CouponList.tsx。多选模式的官方示例位于 demo/index.vue将chosenCoupon绑定为refnumber[]([])通过#list-button插槽自定义一个“确定”按钮点击后把选中的索引数组提交给结算页同时设置:show-close-buttonfalse隐藏默认底部按钮避免多选场景下出现语义不明确的“不使用优惠”按钮。APICouponCell Props参数说明类型默认值title单元格标题string优惠券chosen-coupon当前选中优惠券的索引number | number[]-1coupons可用优惠券列表Coupon[][]editable能否切换优惠券booleantrueborder是否显示内边框booleantruecurrency货币符号string¥CouponCell的展示逻辑值得留意它会根据chosenCoupon汇总所有选中券的金额叠加value或denominations字段在单元格右侧显示-¥ 15.00这样的汇总金额当chosenCoupon为-1且存在可选券时显示“N 张可用”无券时显示“暂无可用券”。该格式化逻辑位于 CouponCell.tsx。editable控制isLink右侧箭头为false时单元格变为纯展示。CouponList Props参数说明类型默认值v-model:code当前输入的兑换码string-chosen-coupon当前选中优惠券的索引,支持多选类型为[]number | number[]-1coupons可用优惠券列表CouponInfo[][]disabled-coupons不可用优惠券列表CouponInfo[][]enabled-title可用优惠券列表标题string可使用优惠券disabled-title不可用优惠券列表标题string不可使用优惠券exchange-button-text兑换按钮文字string兑换exchange-button-loading是否显示兑换按钮加载动画booleanfalseexchange-button-disabled是否禁用兑换按钮booleanfalseexchange-min-length兑换码最小长度number1displayed-coupon-index滚动至特定优惠券位置number-show-close-button是否显示列表底部按钮booleantrueclose-button-text列表底部按钮文字string不使用优惠input-placeholder输入框文字提示string请输入优惠码show-exchange-bar是否展示兑换栏booleantruecurrency货币符号string¥empty-image列表为空时的占位图string-show-count是否展示可用 / 不可用数量booleantrue参数背后有几处值得展开的源码行为均见 CouponList.tsx兑换按钮的禁用判定buttonDisabled是一个computed当exchangeButtonLoading为false且exchangeButtonDisabled为真、兑换码为空、或兑换码长度小于exchangeMinLength时兑换按钮自动禁用CouponList.tsx。即只要在加载中按钮永不因其它条件被禁用兑换码的自动清空点击兑换后触发exchange事件若没有使用v-model:code绑定则内部currentCode会被自动清空若使用了v-model则清空与否由外部数据决定CouponList.tsx。currentCode的任何变化都会同步触发update:code事件配合v-model:code形成双向绑定CouponList.tsx滚动定位displayedCouponIndex变化时会通过nextTick后调用对应券项的scrollIntoView()自动滚动到指定优惠券CouponList.tsxonMounted时也会执行一次CouponList.tsx列表高度自适应updateListHeight会以「根容器高度不足时回退为windowHeight减去兑换栏与 Tab 头高度」来计算列表可视高度Tab 头固定按 44px 计并监听窗口高度变化实时重算保证内部滚动区域精确贴合弹层CouponList.tsx数量角标showCount为true时Tab 标题会追加(N)形式的可用/不可用数量。CouponList Events事件名说明回调参数change优惠券切换回调index, 选中优惠券的索引exchange兑换优惠券回调code, 兑换码事件语义与源码一一对应点击某张可用券触发change多选模式回传数组点击底部“不使用优惠”按钮触发change单选回传-1多选回传[]点击兑换按钮触发exchange。官方测试用例 index.spec.ts 验证了兑换码为空时点击兑换不会触发exchange输入有效兑换码后才触发输入内容还会依次触发update:code事件未绑定v-model:code时兑换后兑换码会被清空。CouponList Slots名称说明list-footer优惠券列表底部disabled-list-footer不可用优惠券列表底部list-button自定义底部按钮其中list-footer/disabled-list-footer分别渲染在两个 Tab 的列表末尾CouponList.tsx 与 CouponList.tsxlist-button用于完全替换底部“不使用优惠”按钮多选模式下的“确定”按钮正是通过该插槽实现的CouponList.tsx。CouponInfo 数据结构优惠券列表的每一项是一个CouponInfo对象键名说明类型id优惠券 idstringname优惠券名称stringcondition满减条件stringstartAt卡有效开始时间 (时间戳, 单位秒)numberendAt卡失效日期 (时间戳, 单位秒)numberdescription描述信息优惠券可用时展示stringreason不可用原因优惠券不可用时展示stringvalue折扣券优惠金额单位分numbervalueDesc折扣券优惠金额文案stringunitDesc单位文案string从源码的类型定义看Coupon.tsxCouponInfo还支持discount折扣如88表示 8.8 折、denominations面额单位分、originCondition原始满减门槛等字段。券面的展示优先级为优先使用valueDesc unitDesc组合文案如1.5元、8.8折否则若有denominations显示货币符号 格式化面额否则若有discount显示X.X折以上都没有则显示为空。金额与折扣的格式化逻辑去除无意义小数位位于 coupon/utils.tsformatAmount按「整数不保留小数、整十保留 1 位、其余保留 2 位」处理formatDiscount仅在非整数折扣时保留 1 位小数。有效期文案由startAt、endAt秒级时间戳格式化为年.月.日 - 年.月.日coupon/utils.ts。此外当优惠券处于不可用状态被放入disabledCoupons时组件展示reason不可用原因而非description且不再显示勾选复选框Coupon.tsx。类型定义组件导出以下类型定义import type { CouponCellProps, CouponListProps, CouponInfo } from vant;CouponListProps由 couponListProps 通过ExtractPropTypes推导而来CouponCellProps同理CouponListThemeVars、CouponCellThemeVars则分别定义在 types.ts 与 coupon-cell/types.ts供 CSS 变量类型提示使用。主题定制样式变量组件提供了下列 CSS 变量可用于自定义样式使用方法请参考 ConfigProvider 组件。名称默认值描述--van-coupon-margin0 var(--van-padding-sm) var(--van-padding-sm)---van-coupon-content-height84px---van-coupon-content-padding14px 0---van-coupon-content-text-colorvar(--van-text-color)---van-coupon-backgroundvar(--van-background-2)---van-coupon-active-backgroundvar(--van-active-color)---van-coupon-radiusvar(--van-radius-lg)---van-coupon-shadow0 0 4px rgba(0, 0, 0, 0.1)---van-coupon-head-width96px---van-coupon-amount-colorvar(--van-danger-color)---van-coupon-amount-font-size30px---van-coupon-currency-font-size40%---van-coupon-name-font-sizevar(--van-font-size-md)---van-coupon-disabled-text-colorvar(--van-text-color-2)---van-coupon-description-paddingvar(--van-padding-xs) var(--van-padding-md)---van-coupon-description-border-colorvar(--van-border-color)---van-coupon-checkbox-colorvar(--van-danger-color)---van-coupon-list-backgroundvar(--van-background)---van-coupon-list-field-padding5px 0 5px var(--van-padding-md)---van-coupon-list-exchange-button-height32px---van-coupon-list-close-button-height40px---van-coupon-list-empty-tip-colorvar(--van-text-color-2)---van-coupon-list-empty-tip-font-sizevar(--van-font-size-md)---van-coupon-list-empty-tip-line-heightvar(--van-line-height-md)---van-coupon-cell-selected-text-colorvar(--van-text-color)-其中--van-coupon-*系列变量作用于单个优惠券卡片面额区、条件区、有效期、描述等定义于 coupon/index.less--van-coupon-list-*系列变量作用于整个选择器背景、兑换栏、底部按钮、空态提示声明于 coupon-list/index.less--van-coupon-cell-selected-text-color则作用于单元格选中态文字颜色。所有变量的默认值均复用 Vant 的基础设计令牌如--van-danger-color、--van-background等因此通过全局或局部ConfigProvider覆盖这些令牌即可实现整套换肤。源码级原理小结从整体实现看CouponList的架构可概括为三个层次顶部兑换栏exchange-bar由Field兑换码输入框最长 20 字符Button兑换按钮组成负责v-model:code的双向绑定与exchange事件抛出CouponList.tsx中部 Tabs 双列表基于Tabs/Tab实现“可使用优惠券”与“不可使用优惠券”两个页签列表高度按弹层动态计算并支持内部滚动空列表时渲染Empty占位可自定义emptyImageCouponList.tsx底部操作区默认渲染“不使用优惠”按钮支持list-button插槽完全替换CouponList.tsx。单张券的渲染由Coupon组件承担它负责券面金额、满减条件、有效期、描述/不可用原因与选中态复选框的展示测试用例 index.spec.ts 覆盖了快照渲染、空列表、自定义空图、兑换事件与插槽渲染等关键行为可作为你二次开发时的回归参考。结语CouponCellCouponList是 Vant 提供的开箱即用的优惠券选择完整方案单元格负责汇总展示列表负责选择、兑换与禁用券浏览CouponInfo数据结构天然兼容“满减券、折扣券、面额券”三类常见形态。接入时只需维护coupons、disabledCoupons、chosenCoupon三个状态并响应change/exchange两个事件再结合ConfigProvider与样式变量即可快速融入业务设计体系。【免费下载链接】vantA lightweight, customizable Vue UI library for mobile web apps.项目地址: https://gitcode.com/GitHub_Trending/va/vant创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考