ARTICLE DETAIL

资讯详情

深耕郑州网站建设与运营推广的一线实战洞察。

Element Plus Space 组件完全指南:布局间距、Spacer 分隔与容器填充实战

Element Plus Space 组件完全指南:布局间距、Spacer 分隔与容器填充实战 Element Plus Space 组件完全指南布局间距、Spacer 分隔与容器填充实战【免费下载链接】element-plus A Vue.js 3 UI Library made by Element team项目地址: https://gitcode.com/GitHub_Trending/el/element-plus导读本文围绕 Vue 3 UI 组件库 Element Plus 中的Space 组件展开系统讲解如何用它在多个组件之间快速建立统一、可维护的间距布局替代用多个 Divider 硬切元素的繁琐写法。读完本文你将掌握 Space 的direction、size、wrap、spacer、alignment、fill/fill-ratio等全部核心 API 的用法与底层实现原理并能在真实项目中正确规避与ElSlider等依赖祖先宽度的组件共存时的已知陷阱。文中所有结论均以本仓库Element Plus官方文档、示例代码与源码实现为依据。为什么需要 Space告别Divider 堆叠式布局虽然官方文档提供了 Divider 组件但在需要将多个元素彼此分隔开的场景中往往不止需要一个分割线。逐个在元素之间堆叠 Divider不仅让模板代码变得冗长丑陋后期维护成本也很高。Space 组件的定位正是解决这个问题——它以统一的间距管理取代手工分割提供生产力和代码优雅度双赢的方案。从文档的描述来看Space 的设计哲学是用统一空间unified space分隔各组件它并不引入额外的边框或线条而是通过 Flex 布局在子元素之间建立一致的间隙这与 Divider 的显式分隔线语义形成互补。基础用法快速建立组件间距Space 最基础的使用方式就是把它当作容器将需要分隔的组件放入默认插槽。以下示例来自 basic.vue展示了用wrap包装多个卡片的效果template el-space wrap el-card v-fori in 3 :keyi classbox-card stylewidth: 250px template #header div classcard-header spanCard name/span el-button classbutton textOperation button/el-button /div /template div v-foro in 4 :keyo classtext item {{ List item o }} /div /el-card /el-space /template源码视角子元素如何被包裹在源码 space.ts 的setup中Space 会对插槽内的子节点执行extractChildren提取逻辑当子节点是 Fragment例如由v-for、v-if、template渲染产生时会递归展开直到拿到真正的 VNode 元素每个有效元素节点都会被包进内部组件Item见 item.ts渲染为一个div classel-space__item若子节点为Comment节点如v-iffalse残留的空模板会直接保留而不包裹测试 space.test.tsx 中的should handle empty conditional templates correctly用例验证了这一点两个真实元素之间夹着两个空模板最终仍只渲染出Item 1|Item 2且只有一个分隔符当插槽内没有任何子节点时组件直接返回null不渲染任何 DOM。这样设计保证了无论子元素来自普通 JSX、v-for列表还是条件渲染间距都能被均匀地套用。垂直布局用direction控制排布方向通过direction属性可以控制布局方向文档明确指出其底层通过flex-direction实现。示例见 vertical-layout.vuetemplate el-space directionvertical el-card v-fori in 2 :keyi classbox-card stylewidth: 250px template #header div classcard-header spanCard name/span el-button classbutton textOperation button/el-button /div /template div v-foro in 4 :keyo classtext item {{ List item o }} /div /el-card /el-space /template源码 use-space.ts 中classes计算属性会生成el-space el-space--horizontal | el-space--vertical这样的类名样式层据此设置对应的 Flex 主轴方向。测试用例也断言了切换direction: vertical后根元素会带上el-space--vertical类见 space.test.tsx 的render test。direction的取值枚举在 space.ts 中定义为[horizontal, vertical]默认值为horizontal。控制间距大小内置尺寸与数值自定义内置尺寸sizeAPI 支持三种内置尺寸对应的像素值在源码 use-space.ts 的SIZE_MAP中明确映射内置尺寸像素值说明small8px默认值default12px中等间距large16px大间距文档明确说明默认尺寸为small即8px。示例 control-size.vue 展示了通过 Radio 组动态切换三种内置尺寸的完整用法template el-space directionvertical alignmentstart :size30 el-radio-group v-modelsize el-radio valuelargeLarge/el-radio el-radio valuedefaultDefault/el-radio el-radio valuesmallSmall/el-radio /el-radio-group el-space wrap :sizesize el-card v-fori in 3 :keyi classbox-card stylewidth: 250px template #header div classcard-header spanCard name/span el-button classbutton textOperation button/el-button /div /template div v-foro in 4 :keyo classtext item {{ List item o }} /div /el-card /el-space /el-space /template script langts setup import { ref } from vue import type { ComponentSize } from element-plus const size refComponentSize(default) /script数值类型完全自定义当内置尺寸无法满足业务需要时可以传入number 类型的像素值。示例 customized-size.vue 用el-slider实时驱动间距大小template el-slider v-modelsize / el-space wrap :sizesize el-card v-fori in 2 :keyi classbox-card stylewidth: 250px template #header div classcard-header spanCard name/span el-button classbutton textOperation button/el-button /div /template div v-foro in 4 :keyo classtext item {{ List item o }} /div /el-card /el-space /template script langts setup import { ref } from vue const size ref(20) /script数组类型分别控制水平与垂直间距size还支持[number, number]形式的数组分别代表水平间距column-gap与垂直间距row-gap。源码 use-space.ts 中watchEffect对此有专门分支if (isArray(size)) { const [h 0, v 0] size horizontalSize.value h verticalSize.value v }测试 space.test.tsx 的sizes用例验证了sizelarge→ 样式gap: 16pxsize{30}→ 样式gap: 30pxsize{[10, 20]}→ 样式同时包含column-gap: 10px与row-gap: 20px传入非法值如unknown时会触发warnHandler警告并回退到8px默认间距。方向与换行对间距的联动规则值得注意的是源码 use-space.ts 中有一条特殊逻辑当wrap或fill为 true 且方向为horizontal时水平与垂直间距会同时取size值horizontalSize.value verticalSize.value val否则横向布局只设置column-gap纵向布局只设置row-gap。这意味着开启自动换行后换行产生的行与行之间也会带上相同间距视觉上更统一。⚠️ 已知陷阱文档官方提示不要将ElSpace与依赖祖先宽度高度的组件一起使用例如ElSlider。在这种组合下拖动滑块手柄时条体会随之变宽导致光标与手柄之间出现错位。如果你需要类似滑杆 间距的效果建议参照 customized-size.vue 的做法把el-slider放在el-space外部仅用它的值去驱动 Space 的size。自动换行用wrap控制横向溢出在水平模式下当子元素总宽度超过容器时默认不会换行Flex 的nowrap行为。传入wrap布尔类型即可开启自动换行。示例 auto-wrapping.vue 用 20 个按钮演示了换行效果template el-space wrap div v-fori in 20 :keyi el-button text Text button /el-button /div /el-space /template从源码 use-space.ts 看containerStyle中wrap || fill为真时会给容器加上flexWrap: wrap样式。测试render test断言了这一点设置wrap: true后根元素样式包含flex-wrap: wrap。Spacer让分隔不再只是空白有时候我们希望元素之间出现的不只是空白而是某种显式分隔物此时可使用spacer。该属性支持三种类型字符串、数字、VNode详见 API 表格类型为string / number / VNode。字面量类型 Spacer传入字符串或数字字面量例如用|作为分隔符示例 literal-type-spacer.vuetemplate el-space :sizesize spacer| div v-fori in 2 :keyi el-button button {{ i }} /el-button /div /el-space /template script langts setup import { ref } from vue const size ref(10) /scriptVNode 类型 Spacerspacer同样可以是一个VNode从而实现更丰富的分隔视觉。示例 vnode-type-spacer.vue 用h()渲染函数创建了一个垂直方向的ElDivider作为分隔template el-space :sizesize :spacerspacer div v-fori in 2 :keyi el-button button {{ i }} /el-button /div /el-space /template script langts setup import { h, ref } from vue import { ElDivider } from element-plus const size ref(10) const spacer h(ElDivider, { direction: vertical }) /script源码视角Spacer 的插入规则源码 space.ts 中spacer的渲染逻辑值得关注只在相邻元素之间插入extractedChildren.reduce遍历时只有当idx ! len非最后一个元素才会追加 spacer因此 N 个元素只会有 N-1 个分隔物。测试用例should render with spacer验证2 个元素 1 个|分隔符 → 根元素共 3 个子节点文本按分隔符拆分得到 2 段VNode 直接克隆复用若spacer本身是 VNode通过isVNode判断会使用cloneVNode克隆后插入避免同一 VNode 被多处复用时出现渲染问题字符串则通过createTextVNode创建文本节点垂直方向宽度修正当direction vertical时包裹 spacer 的span会被强制加上width: 100%样式——注释说明这是因为垂直布局下 spacer 若继承父级宽度而未显式设置间隔可能会消失服务端渲染SSR兼容测试should render every component vnode spacer after hydration使用renderToStringcreateSSRApp验证了 VNode spacer 在 hydration 之后仍能正确渲染出 2 个分隔元素3 个元素 → 2 个分隔。Alignment对齐方式的完整控制alignment属性用于调整子节点在交叉轴上的对齐方式取值范围与 CSS 的align-items一致如flex-start、center、flex-end、stretch、baseline等。示例 alignment.vue 展示了在同一个容器中混排字符串、按钮、卡片等高矮不一的元素时不同对齐值的效果差异template div classalignment-container el-space string el-button button /el-button el-card template #header header /template body /el-card /el-space /div div classalignment-container el-space alignmentflex-start string el-button button /el-button el-card template #header header /template body /el-card /el-space /div div classalignment-container el-space alignmentflex-end string el-button button /el-button el-card template #header header /template body /el-card /el-space /div /template style .alignment-container { width: 240px; margin-bottom: 20px; padding: 8px; border: 1px solid var(--el-border-color); } /style实现上源码 use-space.ts 的containerStyle会直接生成alignItems: props.alignment透传给容器的内联样式默认值为center。对齐值传入时会经过definePropTypeAlignItems(String)的类型约束。填充容器fill与fillRatio的完整语义fill子节点自动填满容器通过fillBoolean 类型参数可以控制子节点是否自动填充容器。开启后子节点的宽度会自动适配容器宽度示例 fill.vuetemplate div div stylemargin-bottom: 15pxfill: el-switch v-modelfill //div el-space :fillfill wrap el-card v-fori in 3 :keyi classbox-card template #header div classcard-header spanCard name/span el-button classbutton textOperation button/el-button /div /template div v-foro in 4 :keyo classtext item {{ List item o }} /div /el-card /el-space /div /template script langts setup import { ref } from vue const fill ref(true) /scriptfillRatio自定义填充比例fillRatio参数用于自定义填充比例默认值为100即按父容器宽度的100%进行填充。需要特别注意的是水平布局与垂直布局的表现略有不同具体差异可在 fill-ratio.vue 的示例中直观对比该示例同时提供direction切换和fillRatio滑杆template div div stylemargin-bottom: 15px direction: el-radio v-modeldirection valuehorizontalhorizontal/el-radio el-radio v-modeldirection valueverticalvertical/el-radio /div div stylemargin-bottom: 15px fillRatio:el-slider v-modelfillRatio / /div el-space fill wrap :fill-ratiofillRatio :directiondirection stylewidth: 100% el-card v-fori in 5 :keyi classbox-card template #header div classcard-header spanCard name/span el-button classbutton textOperation button/el-button /div /template div v-foro in 4 :keyo classtext item {{ List item o }} /div /el-card /el-space /div /template script langts setup import { ref } from vue import type { SpaceInstance } from element-plus const direction refSpaceInstance[direction](horizontal) const fillRatio ref(30) /script源码视角fill 的底层样式源码 use-space.ts 中itemStyle计算属性揭示了 fill 的实现机制const itemStyle computedStyleValue(() { return props.fill ? { flexGrow: 1, minWidth: ${props.fillRatio}% } : {} })即每个el-space__item会获得flex-grow: 1与min-width: {fillRatio}%。测试fill用例验证fill开启时容器样式含flex-wrap: wrapitem 样式含flex-grow: 1与min-width: 100%将fillRatio改为50后item 的min-width变为50%。API 参考Attributes属性名称说明类型默认值alignment子元素的对齐方式^[enum]center \| normal \| stretch \| ...同 CSS align-itemscenterclass类名^[string] / ^[object] / ^[array]—direction排布方向^[enum]vertical \| horizontalhorizontalprefix-clsspace-item 的类名前缀^[string]—style额外样式^[string] / ^[object]CSSProperties \| CSSProperties[] \| string[]—spacer分隔符^[string] / ^[number] / ^[VNode]—size间距大小^[enum]default \| small \| large/ ^[number] / ^[array][number, number]smallwrap是否自动换行^[boolean]falsefill是否填充容器^[boolean]falsefill-ratio填充比例^[number]100需要补充的源码级细节size 的取值约束源码 space.ts 中size的validator要求要么是数字要么是长度为 2 且元素全为数字的数组同时values: componentSizes约束了字符串只能是内置尺寸枚举。测试证明超出约束的值会触发警告并回退到8px。spacer 的取值约束validator要求必须是isVNode(val) || isNumber(val) || isString(val)。prefix-cls 的作用内部SpaceItem渲染时使用${props.prefixCls || ns.b()}__item作为类名见 item.ts默认情况下即el-space__item可用于深度定制 item 的样式钩子。Slots插槽名称说明default需要被统一间距排列的内容完整使用建议优先使用内置尺寸在small8px、default12px、large16px能满足时不要引入魔法数字保证视觉节奏统一需要非对称间距时使用数组[10, 20]可分别控制水平与垂直间隙特别适合开启wrap后的行列间距管理元素需要均分容器宽度时使用fillfillRatio默认 100% 即每行一个元素调低比例可实现一行多个元素按百分比填充分隔符优先用 VNode spacerh(ElDivider, { direction: vertical })比手写|更专业、更可维护注意方向与换行的联动横向 wrap/fill时行距也会自动套用size无需额外处理避开ElSlider类组件遵循文档提示不要把它们放进el-space内部。如果你希望深入学习 Space 的测试覆盖可阅读 space.test.tsx其中涵盖了渲染、尺寸映射、spacer、fill 与空模板处理等关键场景是理解组件行为的极佳参考。【免费下载链接】element-plus A Vue.js 3 UI Library made by Element team项目地址: https://gitcode.com/GitHub_Trending/el/element-plus创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考
返回列表