Vant Cell 单元格组件完全指南:从基础用法到源码级原理解析
2026/9/13 6:48:24 网站建设 项目流程

Vant Cell 单元格组件完全指南:从基础用法到源码级原理解析

【免费下载链接】vantA lightweight, customizable Vue UI library for mobile web apps.项目地址: https://gitcode.com/GitHub_Trending/va/vant

Cell(单元格)是 Vant 移动端 UI 库中最基础也最高频的列表展示组件,常用于信息展示、表单入口与页面导航。本文以 Cell 官方文档 为核心,完整覆盖其引入方式、全部 Props/Slots/Events 配置、CSS 变量主题定制,并结合 Cell.tsx 源码、CellGroup.tsx 源码 与 测试用例 深入剖析其实现原理,帮助你从"会用"进阶到"用得明白"。

介绍与引入

单元格(Cell)是列表中的单个展示项,通常由左侧标题、右侧内容、可选描述信息(label)、图标与箭头构成。它可以单独使用,也可以与CellGroup搭配组成分组列表。

全局注册组件的方式如下(更多注册方式可参考 advanced-usage 组件注册章节):

import { createApp } from 'vue'; import { Cell, CellGroup } from 'vant'; const app = createApp(); app.use(Cell); app.use(CellGroup);

从源码看,注册时组件会被withInstall包装,并声明了全局组件名VanCell(见 cell/index.ts),因此模板中可直接使用<van-cell><van-cell-group>,无需额外引入。

基础用法与卡片风格

Cell可以单独使用,也可以与CellGroup搭配使用,CellGroup可以为Cell提供上下外边框:

<van-cell-group> <van-cell title="单元格" value="内容" /> <van-cell title="单元格" value="内容" label="描述信息" /> </van-cell-group>

通过CellGroupinset属性,可以将单元格转换为圆角卡片风格(从 3.1.0 版本开始支持):

<van-cell-group inset> <van-cell title="单元格" value="内容" /> <van-cell title="单元格" value="内容" label="描述信息" /> </van-cell-group>

边框的实现原理

查看 CellGroup.tsx 源码可以发现,普通模式下CellGroup通过BORDER_TOP_BOTTOM工具类为整个分组添加上下边框;而inset模式下则不再使用该边框类,改由卡片自身的圆角与留白呈现独立分组效果。同时 index.less 中每个.van-cell通过::after伪元素(hairline-bottom混合宏)绘制细分割线,且最后一个单元格(:last-child)与--borderless样式会隐藏该分割线——这就是为什么分组内相邻单元格之间只有一条纤细边框的底层原因。

单元格大小

通过size属性可以控制单元格的大小,可选值为normal(默认)与large

<van-cell title="单元格" value="内容" size="large" /> <van-cell title="单元格" value="内容" size="large" label="描述信息" />

size的类型定义在源码中为export type CellSize = 'normal' | 'large'(见 Cell.tsx)。large尺寸对应的样式变量包括--van-cell-large-vertical-padding(垂直内边距)、--van-cell-large-title-font-size(标题字号)、--van-cell-large-label-font-size(描述字号)等,可参考下方"主题定制"章节统一调整。

展示图标与箭头

左侧图标

通过icon属性在标题左侧展示图标,图标名称与 Icon 组件 的name属性一致(支持内置图标名或图片链接),也可通过icon-prefix自定义图标类名前缀:

<van-cell title="单元格" icon="location-o" />

从源码 Cell.tsx 可以看到,当传入icon属性且未提供icon插槽时,组件内部会渲染一个Icon组件并应用van-cell__left-icon类;icon-prefix会透传给 Icon 组件的class-prefix属性。测试用例也验证了icon-prefix="my-icon"能正确生效(见 test/index.spec.ts)。

右侧箭头

设置is-link属性后会在单元格右侧显示箭头,并且可以通过arrow-direction属性控制箭头方向(可选up/down/left,默认right):

<van-cell title="单元格" is-link /> <van-cell title="单元格" is-link value="内容" /> <van-cell title="单元格" is-link arrow-direction="down" value="内容" />

源码中renderRightIcon(Cell.tsx)的逻辑值得注意:当arrow-direction不是默认的right时,会使用arrow-${direction}图标名(如arrow-down),否则使用arrow。箭头图标颜色由--van-cell-right-icon-color变量控制。

点击反馈与无障碍

is-link不仅展示箭头,还会自动开启点击反馈:源码中const clickable = props.clickable ?? isLink;(Cell.tsx)表示clickable默认继承is-link的值,且当clickable为真时,根节点会附加role="button"tabindex="0"(Cell.tsx),对屏幕阅读器与键盘操作友好。若你只想显示箭头而不想要点击态,可显式传入:clickable="false",测试用例中已覆盖该场景(test/index.spec.ts)。

页面导航

可以通过url属性进行 URL 跳转,或通过to属性进行路由跳转:

<van-cell title="URL 跳转" is-link url="https://github.com" /> <van-cell title="路由跳转" is-link to="index" />

导航底层实现

Vant 将跳转逻辑抽取为独立的route函数(见 composables/use-route.ts),tourlreplace三个属性来自routeProps。其执行顺序为:

  1. 优先判断to且当前环境存在 Vue Router 实例,此时调用router.push(to)(若replacetrue则调用router.replace(to))进行路由跳转,to的类型即 Vue Router 的RouteLocationRawstring | object);
  2. 否则若传入url,则通过location.href = url(或location.replace(url))进行浏览器地址跳转。

CellrouteProps通过extend合并进自身 props(Cell.tsx),并在onClick时调用route。这意味着:只有设置了is-link(或clickable)时,点击才会触发导航,这是源码层面确认的行为。

分组标题

通过CellGrouptitle属性可以指定分组标题,也可以使用title插槽完全自定义标题内容:

<van-cell-group title="分组1"> <van-cell title="单元格" value="内容" /> </van-cell-group> <van-cell-group title="分组2"> <van-cell title="单元格" value="内容" /> </van-cell-group>

从 CellGroup.tsx 源码可见,当title属性或title插槽存在时,渲染结果会拆分为"标题节点 + 分组容器节点"两个部分,标题样式类为van-cell-group__title,其内边距、字号与颜色均可通过下方样式变量定制。

使用插槽自定义内容

当属性无法满足需求时,可以使用插槽来自定义任意区域的内容:

<van-cell value="内容" is-link> <!-- 使用 title 插槽来自定义标题 --> <template #title> <span class="custom-title">单元格</span> <van-tag type="primary">标签</van-tag> </template> </van-cell> <van-cell title="单元格" icon="shop-o"> <!-- 使用 right-icon 插槽来自定义右侧图标 --> <template #right-icon> <van-icon name="search" class="search-icon" /> </template> </van-cell> <style> .custom-title { margin-right: 4px; vertical-align: middle; } .search-icon { font-size: 16px; line-height: inherit; } </style>

Cell共提供 6 个插槽:titlevaluelabeliconright-iconextra。源码层面有三个值得注意的实现细节:

  • valuedefault是别名关系renderValueconst slot = slots.value || slots.default;(Cell.tsx),即不具名内容默认渲染在右侧区域;
  • title插槽支持动态清空:当title插槽渲染结果为空数组时直接返回(Cell.tsx),这是为了配合 Field 组件动态设置空 label 的需求;
  • extra插槽渲染在结构最右侧(Cell.tsx),适合放置按钮、徽标等附加操作元素。

垂直居中

通过center属性可以让Cell的左右内容都垂直居中,适合标题与描述信息较多、行高不一的场景:

<van-cell center title="单元格" value="内容" label="描述信息" />

该属性在渲染时被写入根节点的van-cell--center类,对应 index.less 中的align-items: center样式。

API 一览

CellGroup Props

参数说明类型默认值
title分组标题string-
inset是否展示为圆角卡片风格booleanfalse
border是否显示外边框booleantrue

Cell Props

参数说明类型默认值
title左侧标题number | string-
value右侧内容number | string-
label标题下方的描述信息number | string-
size单元格大小,可选值为largenormalstring-
icon左侧图标名称或图片链接,等同于 Icon 组件的 name 属性(见 Icon 文档)string-
icon-prefix图标类名前缀,等同于 Icon 组件的 class-prefix 属性stringvan-icon
tag根节点对应的 HTML 标签名stringdiv
url点击后跳转的链接地址string-
to点击后跳转的目标路由对象,等同于 Vue Router 的to属性(类型为RouteLocationRaw,支持字符串或对象)string | object-
border是否显示内边框booleantrue
replace是否在跳转时替换当前页面历史booleanfalse
clickable是否开启点击反馈booleannull(默认跟随is-link
is-link是否展示右侧箭头并开启点击反馈booleanfalse
required是否显示表单必填星号booleanfalse
center是否使内容垂直居中booleanfalse
arrow-direction箭头方向,可选值为leftupdownstringright
title-style左侧标题额外样式string | Array | object-
title-class左侧标题额外类名string | Array | object-
value-class右侧内容额外类名string | Array | object-
label-class描述信息额外类名string | Array | object-

源码补充:titlevaluelabel均为numericProp(数字或字符串皆可);border使用truthProp默认值为trueclickablerequired的类型均为boolean | null(Cell.tsx)。tag属性支持任意合法 HTML 标签名,测试中验证了tag="a"的渲染结果(test/index.spec.ts)。

Cell Events

事件名说明回调参数
click点击单元格时触发event: MouseEvent

CellGroup Slots

名称说明
default默认插槽
title自定义分组标题

Cell Slots

名称说明
title自定义左侧标题
value自定义右侧内容(default插槽是其别名)
label自定义标题下方的描述信息
icon自定义左侧图标
right-icon自定义右侧图标
extra自定义单元格最右侧的额外内容

类型定义

组件导出以下类型定义:

import type { CellSize, CellProps, CellGroupProps, CellArrowDirection, } from 'vant';

对应源码中:CellSizeCellArrowDirectionCellProps定义于 cell/Cell.tsx,CellGroupProps定义于 cell-group/CellGroup.tsx,统一在 cell/index.ts 中对外导出。

主题定制:CSS 变量与 ConfigProvider

CellCellGroup提供了丰富的 CSS 变量,可结合 ConfigProvider 组件 在全局或局部统一覆盖,实现品牌化主题。完整变量表如下:

名称默认值描述
--van-cell-font-sizevar(--van-font-size-md)单元格字号
--van-cell-line-height24px单元格行高
--van-cell-vertical-padding10px垂直内边距
--van-cell-horizontal-paddingvar(--van-padding-md)水平内边距
--van-cell-text-colorvar(--van-text-color)文本颜色
--van-cell-backgroundvar(--van-background-2)背景色
--van-cell-border-colorvar(--van-border-color)分割线颜色
--van-cell-active-colorvar(--van-active-color)点击态背景色
--van-cell-required-colorvar(--van-danger-color)必填星号颜色
--van-cell-label-colorvar(--van-text-color-2)描述信息颜色
--van-cell-label-font-sizevar(--van-font-size-sm)描述信息字号
--van-cell-label-line-heightvar(--van-line-height-sm)描述信息行高
--van-cell-label-margin-topvar(--van-padding-base)描述信息上边距
--van-cell-value-colorvar(--van-text-color-2)右侧内容颜色
--van-cell-value-font-sizeinherit右侧内容字号
--van-cell-icon-size16px图标尺寸
--van-cell-right-icon-colorvar(--van-gray-6)右侧箭头颜色
--van-cell-large-vertical-paddingvar(--van-padding-sm)large 尺寸垂直内边距
--van-cell-large-title-font-sizevar(--van-font-size-lg)large 尺寸标题字号
--van-cell-large-label-font-sizevar(--van-font-size-md)large 尺寸描述字号
--van-cell-large-value-font-sizeinheritlarge 尺寸内容字号
--van-cell-group-backgroundvar(--van-background-2)分组背景色
--van-cell-group-title-colorvar(--van-text-color-2)分组标题颜色
--van-cell-group-title-paddingvar(--van-padding-md) var(--van-padding-md) var(--van-padding-xs)分组标题内边距
--van-cell-group-title-font-sizevar(--van-font-size-md)分组标题字号
--van-cell-group-title-line-height16px分组标题行高
--van-cell-group-inset-padding0 var(--van-padding-md)卡片风格分组内边距
--van-cell-group-inset-radiusvar(--van-radius-lg)卡片风格圆角
--van-cell-group-inset-title-paddingvar(--van-padding-md) var(--van-padding-md) var(--van-padding-xs) var(--van-padding-xl)卡片风格分组标题内边距

这些变量的默认值定义在 cell/index.less,并在类型层面对应CellThemeVars(见 cell/types.ts),供使用 TypeScript 的开发者获得变量名的智能提示。

例如,在项目入口通过 ConfigProvider 全局放大单元格的舒适度:

<van-config-provider :theme-vars="{ cellVerticalPadding: '14px', cellHorizontalPadding: '16px', cellFontSize: '16px', cellGroupInsetRadius: '12px', }" > <!-- 应用内容 --> </van-config-provider>

与其它 Vant 组件的组合

Cell在设计上是 Vant 内部大量组件的"底盘":FieldCouponCellContactCardAddressList等组件均复用了cellSharedProps.van-cell样式体系(该共享 props 同样定义于 Cell.tsx)。因此深入理解Cell的 Props、插槽与样式变量体系,有助于举一反三地掌握这些上层组件的行为,例如required星号、center对齐、size尺寸等属性在很多派生组件中语义一致。

完整的交互演示可直接查看 cell/demo/index.vue,其中覆盖了本文介绍的全部用法场景;组件的行为契约则由 cell/test/index.spec.ts 中的 12 个测试用例(插槽渲染、箭头方向、title-style、icon-prefix、clickable 关闭、tag 自定义等)固化保障。

【免费下载链接】vantA lightweight, customizable Vue UI library for mobile web apps.项目地址: https://gitcode.com/GitHub_Trending/va/vant

创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考

需要专业的网站建设服务?

联系我们获取免费的网站建设咨询和方案报价,让我们帮助您实现业务目标

立即咨询