ARTICLE DETAIL

资讯详情

深耕网站视觉设计与运营推广的一线实战洞察。

Vant 4 SwipeCell 滑动单元格组件完全指南:左右滑出操作按钮的交互实现与源码剖析

Vant 4 SwipeCell 滑动单元格组件完全指南:左右滑出操作按钮的交互实现与源码剖析 Vant 4 SwipeCell 滑动单元格组件完全指南左右滑出操作按钮的交互实现与源码剖析【免费下载链接】vantA lightweight, customizable Vue UI library for mobile web apps.项目地址: https://gitcode.com/GitHub_Trending/va/vantSwipeCell 是 Vant 4 移动端组件库中用于实现左右滑动露出操作按钮的单元格组件常见于列表项的删除、收藏、选择等场景。本文以 Vant 仓库中 SwipeCell 的官方中文文档packages/vant/src/swipe-cell/README.zh-CN.md为主体结合组件源码SwipeCell.tsx、类型定义types.ts与单元测试test/index.spec.ts系统讲解其引入方式、插槽用法、异步关闭拦截、完整 API 参数并深入剖析滑动位移、阈值判定、事件冒泡控制等底层实现原理帮助你掌握从会用到懂原理的完整链路。介绍与引入SwipeCell是一个可以左右滑动来展示操作按钮的单元格组件典型应用是列表项左滑出现选择、右滑出现删除/收藏等操作。它属于 Vant 4 组件库中可单独注册的组件之一。通过以下方式全局注册组件更多注册方式参考 组件注册指南import { createApp } from vue; import { SwipeCell } from vant; const app createApp(); app.use(SwipeCell);从源码看SwipeCell通过withInstall包装后导出并在index.ts中声明了VanSwipeCell全局组件类型因此在模板中既可以写van-swipe-cell也可以按需以组件方式使用见 index.ts。代码演示基础用法SwipeCell组件提供了left和right两个插槽用于定义两侧滑动区域的内容中间的默认插槽放置单元格本体van-swipe-cell template #left van-button square typeprimary text选择 / /template van-cell :borderfalse title单元格 value内容 / template #right van-button square typedanger text删除 / van-button square typeprimary text收藏 / /template /van-swipe-cell对应组件内渲染结构为.van-swipe-cell根节点下包裹.van-swipe-cell__wrapper容器按left插槽、默认插槽、right插槽的顺序排列见 SwipeCell.tsx。自定义内容SwipeCell的默认插槽可以嵌套任意内容例如一个商品卡片van-card右侧放置删除按钮van-swipe-cell van-card num2 price2.00 desc描述信息 title商品标题 classgoods-card thumbhttps://fastly.jsdelivr.net/npm/vant/assets/cat.jpeg / template #right van-button square text删除 typedanger classdelete-button / /template /van-swipe-cell style .goods-card { margin: 0; background-color: white; } .delete-button { height: 100%; } /style注意让操作按钮height: 100%可以保证滑动区域内的按钮撑满整列高度视觉上更协调。官方演示代码demo/index.vue中同样使用了该写法。异步关闭通过传入before-close回调函数可以自定义两侧滑动内容关闭时的行为例如在点击删除时弹出确认对话框确认后才真正收起van-swipe-cell :before-closebeforeClose template #left van-button square typeprimary text选择 / /template van-cell :borderfalse title单元格 value内容 / template #right van-button square typedanger text删除 / /template /van-swipe-cellimport { showConfirmDialog } from vant; export default { setup() { // position 为关闭时点击的位置 const beforeClose ({ position }) { switch (position) { case left: case cell: case outside: return true; case right: return new Promise((resolve) { showConfirmDialog({ title: 确定删除吗, }) .then(() resolve(true)) .catch(() resolve(false)); }); } }; return { beforeClose }; }, };底层实现原理before-close本质上是一个拦截器。组件内部通过工具函数callInterceptor定义见 utils/interceptor.ts来执行回调若返回值是Promise则等待其 resolve 为true时执行关闭doneresolve 为false时执行取消canceled若返回普通布尔值则同步决定是否关闭未传入before-close时直接执行关闭见 SwipeCell.tsx。此外在异步关闭进行中isInBeforeClosing为 true期间重复点击会被忽略避免重复触发关闭流程。APIProps参数说明类型默认值name标识符通常为一个唯一的字符串或数字可以在事件参数中获取到number | stringleft-width指定左侧滑动区域宽度单位为pxnumber | stringautoright-width指定右侧滑动区域宽度单位为pxnumber | stringautothreshold滑动触发阈值滑动距离与滑动区域宽度的比例number | string0.15before-close关闭前的回调函数返回false可阻止关闭支持返回 Promise(args) boolean | Promiseboolean-disabled是否禁用滑动booleanfalsestop-propagation是否阻止滑动事件冒泡booleanfalse源码细节补充name使用makeNumericProp()定义默认为空字符串在open/close事件及beforeClose参数中随事件对象一起返回SwipeCell.tsx。left-width/right-width未传时auto组件会通过useRect测量对应插槽容器的实际渲染宽度测试用例should auto calc width通过 mock 元素宽度验证了自动测量逻辑test/index.spec.ts。threshold定义时为 0~1 之间的比例值源码通过 validator 校验value 0 value 1默认0.15即滑动距离超过滑动区域宽度的 15% 才会触发展开。disabled为true时onTouchStart/onTouchMove直接返回完全禁止滑动测试should not allow to drag when using disabled prop对此有覆盖。Slots名称说明default默认显示的内容left左侧滑动区域的内容right右侧滑动区域的内容插槽内容分别渲染在.van-swipe-cell__left与.van-swipe-cell__right容器内SwipeCell.tsx。Events事件名说明回调参数click点击时触发position: left | right | cell | outsideopen打开时触发{ name: string | number, position: left | right }close关闭时触发{ name: string | number, position: left | right | cell | outside }组件在setup中声明emits: [open, close, click]SwipeCell.tsx。其中open事件仅在从未打开到打开!opened时触发一次close事件同理重复调用close()不会重复触发——测试should not trigger close event again if already closed专门验证了这一点。beforeClose 参数beforeClose的第一个参数为对象对象中包含以下属性参数名说明类型eventv4.9.4触发关闭的事件对象MouseEvent | TouchEventname标识符string | numberposition关闭时的点击位置left | right | cell | outside测试should call beforeClose before closing验证了点击单元格cell、左侧按钮left、右侧按钮right时传入的事件对象与位置参数均正确。方法通过 ref 可以获取到 SwipeCell 实例并调用实例方法详见 组件实例方法方法名说明参数返回值open打开单元格侧边栏position:left \| right-close收起单元格侧边栏--底层实现实例方法通过useExpose暴露SwipeCell.tsx。open(side)将位移 offset 设为leftWidth或-rightWidthclose(position)将 offset 重置为 0。位移最终通过transform: translate3d(offset px, 0, 0)作用于.van-swipe-cell__wrapper拖拽中过渡时长为0s、松手后为0.6s弹性回位SwipeCell.tsx。测试用例中通过wrapper.vm.open(left)后断言translate3d(100px, 0, 0)验证了该行为。类型定义组件导出以下类型定义import type { SwipeCellSide, SwipeCellProps, SwipeCellPosition, SwipeCellInstance, } from vant;SwipeCellInstance是组件实例的类型用法如下import { ref } from vue; import type { SwipeCellInstance } from vant; const swipeCellRef refSwipeCellInstance(); swipeCellRef.value?.close();对应的类型定义集中在 types.tsSwipeCellSide left | rightSwipeCellPosition SwipeCellSide | cell | outsideSwipeCellInstance则基于ComponentPublicInstanceSwipeCellProps, SwipeCellExpose构造其中SwipeCellExpose声明了open与close两个方法签名。核心交互原理深入解析位移计算与边界钳制组件基于useTouchcomposables/use-touch.ts封装触摸事件。拖动过程中state.offset被clamp(deltaX startOffset, -rightWidth, leftWidth)限制在左侧展开与右侧展开两个边界之间SwipeCell.tsxclamp工具函数定义于 utils/format.ts。阈值判定逻辑松手时通过toggle(side)判定是否展开设当前 offset 绝对值为offset阈值为opened ? 1 - threshold : threshold当offset width * threshold时展开否则回弹关闭SwipeCell.tsx。测试should use custom threshold prop验证了将threshold调为0.5后滑动 50px区域宽度 100px不会展开、滑动 60px 才会展开。点击位置分发与冒泡控制组件通过getClickHandler(position)分别处理对left、right区域及单元格本体cell的点击并通过useClickAway监听touchstart处理点击外部outside时的关闭SwipeCell.tsx。为了区分点击与滑动拖拽过程中会将lockClick置为 true并在松手后通过setTimeout(..., 0)延迟释放从而在桌面端模拟场景下避免拖拽后误触点击事件测试should not trigger native click event after drag operations in desktop simulation scenarios覆盖。同时touchmove通过useEventListener以非 passive 方式监听消除了 Chrome 中的相关警告并允许preventDefault。常见问题在桌面端无法操作组件参见 桌面端适配。SwipeCell 的滑动交互基于触摸事件桌面端需要通过 Vant 官方提供的vant-touch-emulator见 packages/vant-touch-emulator/src/index.js在 PC 上模拟 touch 事件才能正常拖拽操作否则请使用鼠标无法触发的问题可通过引入该模拟器解决。【免费下载链接】vantA lightweight, customizable Vue UI library for mobile web apps.项目地址: https://gitcode.com/GitHub_Trending/va/vant创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考
返回列表