尧图网站设计 尧图网站设计YAOTU DESIGN
ARTICLE DETAIL

资讯详情

深耕网站设计与一线实操的经验洞察。

Vant Empty 空状态组件完全指南:图片类型、自定义尺寸与主题定制

Vant Empty 空状态组件完全指南:图片类型、自定义尺寸与主题定制 Vant Empty 空状态组件完全指南图片类型、自定义尺寸与主题定制【免费下载链接】vantA lightweight, customizable Vue UI library for mobile web apps.项目地址: https://gitcode.com/GitHub_Trending/va/vant导读在移动端 Web 应用中列表为空、搜索无结果、网络异常、操作失败等场景都需要用空状态来占位提示避免用户面对空白页面产生困惑。本文以 Vant 4packages/vant的 Empty 组件为核心从组件注册、五种内置占位图片的源码实现、image-size的尺寸换算规则含数组分别设置宽高的原理、三个插槽的渲染优先级到 CSS 变量主题定制与EmptyThemeVars类型定义逐层拆解一个轻量空状态组件从使用到源码的完整链路。读完本文你将能熟练在任何业务场景中快速接入、定制 Vant Empty并理解其内部 SVG 内置图标的实现机制。一、组件定位与引入Empty 是 Vant 提供的空状态时的占位提示组件见 README.zh-CN.md。它本身不承载业务逻辑核心职责是在数据为空时给出一张占位图 一行描述文字并允许开发者在底部插入操作按钮如去逛逛重新加载引导用户完成下一步动作。全局注册推荐通过app.use全局注册更多注册方式参见组件注册import { createApp } from vue; import { Empty } from vant; const app createApp(); app.use(Empty);注册后即可在模板中使用van-empty标签。从源码看这一能力由 index.ts 中的withInstall封装提供它同时导出了Empty、emptyProps、EmptyProps类型与EmptyThemeVars类型并通过declare module vue将VanEmpty声明进全局组件类型保证 TSX / 模板中的类型提示完整export const Empty withInstall(_Empty); export { emptyProps } from ./Empty; export type { EmptyProps } from ./Empty; export type { EmptyThemeVars } from ./types;组件结构与渲染层级在 Empty.tsx 的渲染函数中组件根节点为van-emptyflex 纵向居中布局内部依次渲染三个区块div classvan-empty div classvan-empty__image !-- 图片区宽度/高度由 image-size 控制 -- p classvan-empty__description !-- 描述文字可选 -- div classvan-empty__bottom !-- 底部插槽内容可选 -- /div该组件仅依赖 Vue 内置能力与useId用于生成 SVG 渐变色 id 防止冲突、getSizeStyle尺寸换算两个工具函数无任何外部依赖是典型的轻量型组件。二、五种图片形态从内置 SVG 到自定义 URL1. 基础用法van-empty description描述文字 /不传image时使用默认图片default类型即商品/内容陈列插画。2. 图片类型error / network / searchEmpty 内置了多种占位图片类型可在不同业务场景下直接切换!-- 通用错误 -- van-empty imageerror description描述文字 / !-- 网络错误 -- van-empty imagenetwork description描述文字 / !-- 搜索提示 -- van-empty imagesearch description描述文字 /对应关系在 Empty.tsx 的PRESET_IMAGES映射表中清晰可见const PRESET_IMAGES: Recordstring, () JSX.Element { error: renderError, search: renderSearch, network: renderNetwork, default: renderMaterial, };源码实现细节这四种内置图片全部是内联 SVGviewBox0 0 160 160而非网络图片资源因此零网络请求、零加载耗时天然适配弱网环境可被 CSS 变量控制颜色与尺寸跟随主题色变化通过renderBuilding()建筑剪影、renderCloud()云朵等函数复用公共图形元素再用renderStop/renderStops生成linearGradient/radialGradient渐变保证多张插画风格统一每个 SVG 内部的id通过useId()getId(num)生成唯一前缀如${baseId}-8避免页面中同时存在多个 Empty 实例时 SVG 渐变 id 冲突。3. 自定义图片URL需要替换为业务自有图片时直接在image中传入图片 URL同时可配合image-size控制展示尺寸van-empty imagehttps://fastly.jsdelivr.net/npm/vant/assets/custom-empty-image.png image-size80 description描述文字 /渲染优先级见 Empty.tsx 的renderImage插槽slots.image 内置类型error/search/network/defaultimage为 URL 时渲染img。即传入的 URL 若恰好等于某个内置类型名如error会命中内置 SVG 而不是img这一点在业务中传入动态图片名时需要注意。三、自定义大小image-size 的三种取值形态image-size是 Empty 使用频率最高的定制属性支持number | string | Array三种形态!-- 不指定单位默认为 px -- van-empty image-size100 description描述文字 / !-- 指定单位支持 rem, vh, vw 等 -- van-empty image-size10rem description描述文字 / !-- 数组格式第一项为宽度第二项为高度 -- van-empty :image-size[60, 40] description描述文字 /底层换算原理addUnit 与 getSizeStyle尺寸换算逻辑由 utils/format.ts 的addUnit与getSizeStyle完成export function addUnit(value?: Numeric): string | undefined { if (isDef(value)) { return isNumeric(value) ? ${value}px : String(value); } return undefined; } export function getSizeStyle( originSize?: Numeric | Numeric[], ): CSSProperties | undefined { if (isDef(originSize)) { if (Array.isArray(originSize)) { return { width: addUnit(originSize[0]), height: addUnit(originSize[1]), }; } const size addUnit(originSize); return { width: size, height: size }; } }可以看到纯数字如100会被自动追加px单位带单位的字符串如10rem、50vw、30vh原样透传因此除rem/vh/vw外%、em等合法 CSS 单位同样可用数组[w, h]分别映射到width与height第一项宽度、第二项高度同样遵循数字补 px、字符串透传规则。该 style 最终被绑定到图片容器.van-empty__image上Empty.tsx容器内的img通过 CSSwidth/height: 100%自动撑满见 index.less因此调整image-size即可等比缩放整张插画。测试用例佐证test/index.spec.ts完整验证了三种形态的换算结果// imageSize: 50 → width/height 50px // imageSize: 1vw → width/height 1vw // imageSize: [20, 10] → width 20px, height 10px四、底部内容与三个插槽默认插槽底部按钮空状态页最常见的诉求是给用户一个下一步动作通过默认插槽即可在组件下方插入任意内容van-empty description描述文字 van-button round typeprimary classbottom-button按钮/van-button /van-empty style .bottom-button { width: 160px; height: 40px; } /style插槽内容会被渲染进.van-empty__bottom容器并通过--van-empty-bottom-margin-top默认24px与描述文字拉开间距Empty.tsx。三个插槽的优先级与用途名称说明渲染位置覆盖优先级default自定义底部内容.van-empty__bottom仅当存在时渲染image自定义图片含插画/动图/自定义 DOM.van-empty__image高于imagepropdescription自定义描述文字富文本、多行、高亮关键词.van-empty__description高于descriptionprop描述文字的渲染逻辑Empty.tsx为插槽优先、prop 兜底const renderDescription () { const description slots.description ? slots.description() : props.description; if (description) { return p class{bem(description)}{description}/p; } };即传入description插槽时忽略descriptionprop两者皆为空时不渲染p标签避免留白。测试用例test/index.spec.ts分别验证了image/description/default三个插槽均可正确渲染imagenetwork时输出 SVG。五、API 一览Props参数说明类型默认值image图片类型可选值为errornetworksearch支持传入图片 URLstringdefaultimage-size图片大小默认单位为pxnumber | string | Array-description图片下方的描述文字string-与源码 Empty.tsx 中emptyProps的定义一一对应export const emptyProps { image: makeStringProp(default), imageSize: [Number, String, Array] as PropTypeNumeric | [Numeric, Numeric], description: String, };其中image使用makeStringProp(default)声明默认值为字符串default这也是未传image时命中内置default插画的直接原因。Slots名称说明default自定义底部内容image自定义图片description自定义描述文字类型定义组件导出以下类型定义可在 TS 项目中获得完整的 props 类型推导import type { EmptyProps } from vant;六、主题定制CSS 变量与 EmptyThemeVarsEmpty 提供 8 个 CSS 变量用于自定义样式使用方法请参考 ConfigProvider 组件。变量在 index.less 中定义于:root, :host可在任意层级覆盖名称默认值描述--van-empty-paddingvar(--van-padding-xl) 0组件整体内边距--van-empty-image-size160px图片默认尺寸--van-empty-description-margin-topvar(--van-padding-md)描述文字上边距--van-empty-description-padding0 60px描述文字内边距--van-empty-description-colorvar(--van-text-color-2)描述文字颜色--van-empty-description-font-sizevar(--van-font-size-md)描述文字字号--van-empty-description-line-heightvar(--van-line-height-md)描述文字行高--van-empty-bottom-margin-top24px底部内容上边距这些变量直接驱动 index.less 中的.van-empty各区块样式容器为 flex 纵向居中布局图片容器默认160px × 160px由--van-empty-image-size决定这也是不传image-size时图片大小的来源描述文字采用次要文本色--van-text-color-2。类型化的主题变量组件同步导出了EmptyThemeVars类型types.ts将上述 8 个 CSS 变量映射为可选的 camelCase 属性export type EmptyThemeVars { emptyPadding?: string; emptyImageSize?: string; emptyDescriptionMarginTop?: string; emptyDescriptionPadding?: string; emptyDescriptionColor?: string; emptyDescriptionFontSize?: string; emptyDescriptionLineHeight?: number | string; emptyBottomMarginTop?: string; };配合 ConfigProvider 的theme-vars属性可做到主题变量完全类型安全van-config-provider :theme-varsthemeVars van-empty description暂无数据 / /van-config-providerimport type { EmptyThemeVars } from vant; const themeVars: EmptyThemeVars { emptyImageSize: 200px, emptyDescriptionColor: #646566, };深色模式适配一个值得注意的实现细节在深色主题下index.less 通过.van-theme-dark .van-empty { opacity: 0.5; }将整个空状态整体降为 50% 透明度避免内置 SVG 插画在深色背景下过于刺眼这是 Vant 全局深色模式体系在 Empty 上的统一处理。七、完整实战示例结合 Vant 官方演示源码demo/index.vue一个覆盖搜索无结果 底部刷新按钮 自定义尺寸的典型组合template van-empty imagesearch :image-size120 description没有找到相关商品 van-button round typeprimary classretry-button 重新搜索 /van-button /van-empty /template style .retry-button { width: 160px; height: 40px; } /style结语Vant 的 Empty 组件在轻量与可扩展之间做了很好的平衡内置 SVG 插画零网络开销、imageprop 与三个插槽提供了从换图到全自定义的渐进式定制能力、image-size的addUnit换算让尺寸控制既简单又灵活、8 个 CSS 变量与EmptyThemeVars类型让主题定制安全可控。理解其 Empty.tsx 的渲染优先级与 utils/format.ts 的尺寸换算逻辑后你在任何空数据业务场景下都能快速给出高质量的占位方案。【免费下载链接】vantA lightweight, customizable Vue UI library for mobile web apps.项目地址: https://gitcode.com/GitHub_Trending/va/vant创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考
返回列表