资讯动态

Vben Descriptions 详解:基于 Vue 3 与 shadcn-ui 的只读信息展示组件实战指南

发布时间:2026/9/10 10:52:21 来源:尧图企业网站定制
Vben Descriptions 详解基于 Vue 3 与 shadcn-ui 的只读信息展示组件实战指南【免费下载链接】vue-vben-adminA modern vue admin panel built with Vue3, Shadcn UI, Vite, TypeScript, and Monorepo. Its fast!项目地址: https://gitcode.com/GitHub_Trending/vu/vue-vben-adminVbenDescriptions是 vue-vben-admin 中用于展示一组只读字段的通用组件常见于详情页与信息预览场景。它基于 shadcn-ui 构建API 参考 Ant Design Vue 的 Descriptions 设计支持响应式列数、跨列span、边框与垂直布局等能力并提供数据驱动items与子组件声明VbenDescriptionsItem两种使用方式。读完本文你将掌握该组件的全部 Props / Slots / 类型定义、两种用法的最佳实践以及其响应式列数解析与行装箱算法的底层原理。如果本文未覆盖你需要的细节可结合 docs/src/demos/vben-descriptions 下的在线示例basic、bordered、vertical、size、span、custom对照学习。::: info 开始之前 组件支持两种用法通过items数据驱动推荐或使用VbenDescriptionsItem子组件声明条目。两者同时提供时items优先生效。 :::基础用法数据驱动的 items通过items传入字段数组每项包含label与content。列数默认按断点自适应xs1 列、sm2 列、md及以上 3 列。参考 demos/vben-descriptions/basic/index.vue 的实现script langts setup import { VbenDescriptions } from vben/common-ui; const items [ { content: Vben, label: 用户名 }, { content: 13800138000, label: 手机号 }, { content: 中国 · 杭州, label: 居住地 }, { content: 前端工程师, label: 职位 }, { content: 这是一段较长的备注信息用于演示跨列展示。, label: 备注, span: 3, }, ]; /script template VbenDescriptions :itemsitems / /template组件的导出入口位于 packages/core/ui-kit/shadcn-ui/src/components/descriptions/index.ts并从 packages/effects/common-ui/src/components/index.ts 统一对外提供VbenDescriptions、VbenDescriptionsItem及DescriptionsItemType、DescriptionsProps、DescriptionsSize、DescriptionsColumn等类型。在组件内部descriptions.vue优先读取props.items只有items为空时才回退到默认插槽解析这正是文档所述items优先的实现来源const resolvedItems computedDescriptionsItemType[](() { if (props.items props.items.length 0) return props.items; const nodes (slots.default?.() ?? []) as VNode[]; return parseItemsFromSlot(nodes); });边框模式Bordered与标题/操作区设置bordered即可切换为带边框的表格样式可配合title属性与#extra插槽标题右侧的操作区域一起使用VbenDescriptions bordered title用户信息 template #extra a-button sizesmall typeprimary编辑/a-button /template VbenDescriptionsItem label用户名Vben/VbenDescriptionsItem VbenDescriptionsItem label邮箱vbenexample.com/VbenDescriptionsItem /VbenDescriptions从渲染实现descriptions-row.vue看边框模式与普通模式在表格结构上有本质区别水平 边框每个条目拆分为labelth与contenttd两个单元格content 的colspan按(span ?? 1) * 2 - 1计算保证与 label 配对后整体占位正确水平 非边框每个条目只有一个单元格tdlabel 与 content 通过 flex 容器同行展示垂直布局每个条目占用两行——标签行th与内容行td各自独立。非边框模式还做了细节处理当未启用bordered时为表格追加[tbodytr:last-childtd]:pb-0类去掉最后一行的底部间距避免与下方内容间距过大见 descriptions.vue 中的tableClass计算逻辑。标题区由hasHeader计算属性驱动只要title/extra属性或同名插槽任一存在即渲染标题行descriptions.vueconst hasHeader computed( () !!props.title || !!props.extra || !!slots.title || !!slots.extra, );垂直布局Vertical Layout使用layoutvertical可将标签置于内容上方VbenDescriptions layoutvertical :itemsitems /在 descriptions-row.vue 中垂直布局渲染为两个独立的tr第一行以tagth、typelabel渲染标签第二行以tagtd、typecontent渲染内容两者的colspan均为item.span ?? 1保证标签与内容在视觉上严格对齐。尺寸Sizessize支持small、middle、large三档默认middle。单元格的间距由 descriptions-cell.vue 中两套常量控制const BORDERED_PADDING: RecordDescriptionsSize, string { large: px-6 py-4, middle: px-4 py-2.5, small: px-3 py-2, }; const PLAIN_PADDING: RecordDescriptionsSize, string { large: pb-6, middle: pb-4, small: pb-2, };边框模式下使用BORDERED_PADDING横向 纵向内边距非边框模式使用PLAIN_PADDING仅底部内边距因为 label 与 content 同处一行依靠 flex 横向排布。跨列span与响应式列数在条目上设置span可实现跨多列span取filled时该项会占满当前行的剩余空间并立即换行。column可接收按断点键控的对象实现响应式列数。参考 demos/vben-descriptions/span/index.vuescript langts setup import type { DescriptionsItemType } from vben/common-ui; import { VbenDescriptions } from vben/common-ui; const items: DescriptionsItemType[] [ { content: 1, label: A }, { content: 2span: 2, label: B, span: 2 }, { content: 3, label: C }, { content: 占满当前行剩余空间, label: Dspan: filled, span: filled }, { content: 5, label: E }, ]; /script template !-- 列数随断点变化xs 1 列、sm 2 列、md 及以上 3 列 -- VbenDescriptions bordered :column{ md: 3, sm: 2, xs: 1 } :itemsitems / /template底层实现行装箱算法跨列行为并非简单的 CSScolspan而是由 use-descriptions.ts 中的calcRows行装箱算法在渲染前完成的该算法移植自 antdv-next 的useRow普通条目按span累加列计数count item.span || 1当累加超出总列数时将当前条目的 span 收敛为剩余列数restSpan column - count避免单元格溢出filled条目直接把当前行推入结果并换行最后逐行校验若一行总 span 不足列数则扩展该行最后一项的 span 以占满整行保证表格右侧没有空洞。span同样支持断点键控对象normalizeItems会调用matchScreen将其解析为当前视口下的数字filled则被标记为filled: true在装箱阶段特殊处理。子组件用法VbenDescriptionsItem当不传items时可以在默认插槽中声明VbenDescriptionsItem条目。内容既可通过默认插槽传入也可使用#content插槽自定义VbenDescriptions title自定义渲染 VbenDescriptionsItem label用户名Vben/VbenDescriptionsItem VbenDescriptionsItem label状态 template #content Badge在线/Badge /template /VbenDescriptionsItem /VbenDescriptionsVbenDescriptionsItem本身是一个标记组件见 descriptions-item.vue它的setup直接返回() null不渲染任何 DOM只是作为 props 与插槽的载体。父组件通过parseItemsFromSlotuse-descriptions.ts从默认插槽的 vnode 中收集条目通过flattenVNodes递归展平Fragment并剔除注释节点因此支持条件渲染、v-for等写法通过isItemVNode识别节点既检查type.name VbenDescriptionsItem也检查组件上设置的__isDescriptionsItem标记见 descriptions-item.vue 末尾识别更稳健label/content插槽函数形式优先级高于对应 propscontent插槽又优先于默认插槽。API 参考Descriptions PropsProp说明类型默认值items数据驱动的条目不传时读取默认插槽DescriptionsItemType[]-bordered是否显示边框booleanfalsecolumn每行列数支持断点配置number \| PartialRecordBreakpoint, number{ xs: 1, sm: 2, md: 3, xxxl: 4 }layout布局方向horizontal \| verticalhorizontalsize尺寸small \| middle \| largemiddlecolon是否显示冒号仅非边框的水平布局生效booleantruetitle标题string-extra标题右侧的操作区域string-labelStyle统一的标签样式CSSProperties-contentStyle统一的内容样式CSSProperties-class根节点自定义类名string-以上类型定义与默认值可在 types.ts 与 descriptions.vue 的withDefaults中逐一印证。Descriptions SlotsSlot说明title自定义标题extra标题旁的自定义操作区域default放置VbenDescriptionsItem子组件DescriptionsItem即items数组中的每一项或VbenDescriptionsItem子组件的 props。Prop说明类型默认值label标签string \| number \| (() VNode) \| Component-content内容string \| number \| (() VNode) \| Component-span跨列数filled表示占满当前行剩余number \| filled \| PartialRecordBreakpoint, number1labelStyle标签样式CSSProperties-contentStyle内容样式CSSProperties-key唯一 keystring \| number-注意DescriptionsRenderNodecontent/label的类型支持字符串、数字、渲染函数与组件见 types.ts并通过VbenRenderContent统一渲染。对于数字0渲染层会先转成字符串再交给VbenRenderContent避免被当作 falsy 值隐藏见 descriptions-cell.vue 中的displayLabel/displayContent计算逻辑。DescriptionsItem Slots仅子组件用法下可用。Slot说明default内容等价于contentcontent自定义内容label自定义标签::: tip 断点说明 响应式Breakpoint取值为xs | sm | md | lg | xl | xxl | xxxl像素值与 Ant Design 保持一致sm576、md768、lg992、xl1200、xxl1600、xxxl2000。 :::断点解析与默认列数的源码实现断点的像素定义、命中判断与默认列数均集中在 use-descriptions.ts/** 默认列数映射 */ export const DEFAULT_COLUMN_MAP: RecordDescriptionsBreakpoint, number { lg: 3, md: 3, sm: 2, xl: 3, xs: 1, xxl: 3, xxxl: 4, }; /** 断点像素值 */ const BREAKPOINT_PX { sm: 576, md: 768, lg: 992, xl: 1200, xxl: 1600, xxxl: 2000 };useScreens基于vueuse/core的useBreakpoints监听视口宽度返回当前命中的断点集合xs定义为未命中sm即小于 576pxresolveColumn解析最终列数column为数字时直接返回为对象时以{ ...DEFAULT_COLUMN_MAP, ...column }合并用户配置再通过matchScreen按断点从大到小xxxl → xs取第一个命中的值兜底为 3 列。因此当你不传column时实际生效的是默认映射{ xs: 1, sm: 2, md: 3, xxxl: 4 }文档中xs 1 列、sm 2 列、md 及以上 3 列的表述正是这一默认映射在md及以上断点均为 3、xxxl为 4 的体现。而像 span 示例那样显式传入{ md: 3, sm: 2, xs: 1 }则会完全覆盖默认值。冒号colon的实现细节colon默认true仅在非边框的水平布局中生效。它并非在文本后拼接字符而是通过 CSS 伪元素实现见 descriptions-cell.vue// 冒号通过伪元素追加避免标签为渲染函数时无法拼接 const COLON_CLASS after:content-[:];const labelClass computed(() cn(mr-2 shrink-0 text-muted-foreground, props.colon COLON_CLASS), );这样做的好处是当label是渲染函数或组件时仍然能稳定地附加冒号同时标签统一使用text-muted-foreground弱化视觉层级与内容文字形成对比。样式合并方面descriptions-row.vue 通过mergeStyle将组件级labelStyle/contentStyle与条目级样式合并条目级优先级更高实现统一样式 单项覆盖的组合能力。小结VbenDescriptions是 vue-vben-admin 中面向详情页与信息预览的标准答案日常开发优先使用items数据驱动写法配合默认的断点自适应列数即可零配置落地涉及特殊排版时可利用span/filled、bordered、layoutvertical与#extra插槽按需组合而VbenDescriptionsItem子组件写法则为高度自定义的插槽内容如 badge、按钮、富文本保留了最大灵活性。理解其背后的行装箱算法与断点解析逻辑能帮助你在复杂表单详情场景中准确预测布局行为避免出现单元格溢出或列数不符合预期的问题。【免费下载链接】vue-vben-adminA modern vue admin panel built with Vue3, Shadcn UI, Vite, TypeScript, and Monorepo. Its fast!项目地址: https://gitcode.com/GitHub_Trending/vu/vue-vben-admin创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考

读完文章,也想定制专属网站?

尧图设计师 24 小时内与您沟通定制方案

免费获取报价