- 需要将页面区域自由切分为多个可拖拽调整的面板时。
- 需要水平或垂直布局、面板折叠等功能时。
- 构建 IDE、代码编辑器等可伸缩分栏布局时。
import { Splitter, SplitterPanel } from "@reglow/reui";
初始化面板大小,限制面板大小范围。
<Splitter class="h-400px">
<SplitterPanel :default-size="300" :min="200" :max="500">
<div class="p-4">左侧内容</div>
</SplitterPanel>
<SplitterPanel>
<div class="p-4">右侧内容</div>
</SplitterPanel>
</Splitter>
受控调整尺寸。当 Panel 之间任意一方禁用 resizable,则其拖拽将被禁用。
<script setup lang="ts">
import { ref } from "vue";
import { Splitter, SplitterPanel } from "@reglow/reui";
const sizes = ref<Array<number | string>>(["30%", "70%"]);
function onResize(next: Array<number | string>) {
sizes.value = [...next];
}
</script>
<template>
<Splitter class="h-[240px]" @resize="onResize">
<SplitterPanel :size="sizes[0]">
<div class="p-4">First</div>
</SplitterPanel>
<SplitterPanel :size="sizes[1]">
<div class="p-4">Second</div>
</SplitterPanel>
</Splitter>
<p class="text-sm text-muted-foreground">当前尺寸:{{ sizes.join(" / ") }}</p>
</template>
<script setup>
import { Splitter, SplitterPanel } from "@reglow/reui";
</script>
<template>
<Splitter orientation="vertical" class="h-[260px]">
<SplitterPanel :default-size="200">
<div class="p-4">上部</div>
</SplitterPanel>
<SplitterPanel>
<div class="p-4">下部</div>
</SplitterPanel>
</Splitter>
</template>
配置 collapsible 提供快捷收缩能力。可以通过 min 限制收缩后不能通过拖拽展开。
折叠交互对齐 antd Splitter:
collapsible: { start: true }:折叠按钮出现在面板起始边(水平左侧 / 垂直上侧)拖拽条、分割线右侧,图标 → / ↓(指向结束边);点击后面板折叠(宽度归零)。collapsible: { end: true }:折叠按钮出现在面板结束边(水平右侧 / 垂直下侧)拖拽条、分割线左侧,图标 ← / ↑(指向起始边);点击后面板折叠(宽度归零)。- 面板折叠后,展开按钮出现在分割线另一侧,图标方向互换(
← ↔ →、↑ ↔ ↓)。
<script setup>
import { Splitter, SplitterPanel } from "@reglow/reui";
</script>
<template>
<Splitter class="h-[240px]">
<SplitterPanel :default-size="'40%'" collapsible :min="'20%'">
<div class="p-4">First</div>
</SplitterPanel>
<SplitterPanel collapsible>
<div class="p-4">Second</div>
</SplitterPanel>
<SplitterPanel collapsible>
<div class="p-4">Third</div>
</SplitterPanel>
</Splitter>
</template>
配置 collapsible.showCollapsibleIcon 控制折叠图标显示:true 常显 / false 隐藏 / 'auto'(默认)悬浮拖拽条时显示。
<script setup>
import { Splitter, SplitterPanel } from "@reglow/reui";
</script>
<template>
<Splitter class="h-[240px]">
<SplitterPanel :default-size="'40%'" :collapsible="{ end: true, showCollapsibleIcon: true }">
<div class="p-4">Panel 1</div>
</SplitterPanel>
<SplitterPanel :collapsible="{ start: true, showCollapsibleIcon: true }">
<div class="p-4">Panel 2</div>
</SplitterPanel>
</Splitter>
</template>
<script setup>
import { Splitter, SplitterPanel } from "@reglow/reui";
</script>
<template>
<Splitter class="h-[300px]">
<SplitterPanel :default-size="'20%'" collapsible>
<div class="p-4">Left</div>
</SplitterPanel>
<SplitterPanel>
<Splitter orientation="vertical" class="h-full">
<SplitterPanel>
<div class="p-4">Top</div>
</SplitterPanel>
<SplitterPanel>
<div class="p-4">Bottom</div>
</SplitterPanel>
</Splitter>
</SplitterPanel>
</Splitter>
</template>
双击拖拽条,相邻面板重置为默认大小(defaultSize)。
<script setup lang="ts">
import { ref } from "vue";
import { Splitter, SplitterPanel } from "@reglow/reui";
const message = ref("双击分隔条可将相邻面板重置为默认大小");
</script>
<template>
<Splitter
class="h-[240px]"
@dragger-double-click="message = '已双击,面板重置为默认大小'"
>
<SplitterPanel :default-size="'30%'">
<div class="p-4">Panel 1</div>
</SplitterPanel>
<SplitterPanel :default-size="'70%'">
<div class="p-4">Panel 2</div>
</SplitterPanel>
</Splitter>
<p class="text-sm text-muted-foreground">{{ message }}</p>
</template>
draggerIcon 自定义拖拽图标(字符串 / VNode / 组件,传 null 隐藏),collapsible.icon 自定义折叠图标。
<script setup lang="ts">
import { h } from "vue";
import { Splitter, SplitterPanel } from "@reglow/reui";
const draggerIcon = h("span", { class: "text-[10px] leading-none" }, "↔");
</script>
<template>
<Splitter
class="h-[240px]"
:dragger-icon="draggerIcon"
:collapsible="{ icon: { start: '◀', end: '▶' } }"
>
<SplitterPanel :default-size="'40%'" :min="'20%'" :max="'70%'" collapsible>
<div class="p-4">Panel 1</div>
</SplitterPanel>
<SplitterPanel collapsible>
<div class="p-4">Panel 2</div>
</SplitterPanel>
</Splitter>
</template>
通过 classNames / styles 自定义 root / panel / dragger(dragger 支持 { default, active })。
<script setup>
import { Splitter, SplitterPanel } from "@reglow/reui";
</script>
<template>
<Splitter
class="h-[240px]"
:class-names="{ root: 'bg-muted/30 rounded-lg', dragger: { default: 'bg-primary/10', active: 'bg-primary' } }"
:styles="{ panel: { background: '#fafafa' } }"
>
<SplitterPanel :default-size="'40%'">
<div class="p-4">Panel 1</div>
</SplitterPanel>
<SplitterPanel>
<div class="p-4">Panel 2</div>
</SplitterPanel>
</Splitter>
</template>
拖拽时不会立即更新大小,而是等到松手时才更新。
<script setup>
import { Splitter, SplitterPanel } from "@reglow/reui";
</script>
<template>
<Splitter lazy class="h-[240px]">
<SplitterPanel :default-size="300">
<div class="p-4">面板 1</div>
</SplitterPanel>
<SplitterPanel>
<div class="p-4">面板 2</div>
</SplitterPanel>
</Splitter>
</template>
destroyOnHidden 在折叠(size 为 0)时销毁面板内容,可在单个面板上覆盖。
<script setup lang="ts">
import { ref } from "vue";
import { Splitter, SplitterPanel } from "@reglow/reui";
// 折叠后再展开时,计数会因内容销毁而重置为 0
const count = ref(0);
function onCollapse(state: boolean[]) {
console.log("collapse", state);
}
</script>
<template>
<Splitter destroy-on-hidden class="h-[240px]" @collapse="onCollapse">
<SplitterPanel :default-size="'40%'" collapsible>
<div class="p-4">折叠后内容被销毁</div>
<button class="ml-4" @click="count++">点击计数:{{ count }}</button>
</SplitterPanel>
<SplitterPanel>
<div class="p-4">Panel 2</div>
</SplitterPanel>
</Splitter>
</template>
| 属性 | 类型 | 默认值 | 说明 |
|---|
orientation | "horizontal" | "vertical" | - | 布局方向(与 vertical 同时存在时优先) |
layout | "horizontal" | "vertical" | "horizontal" | 布局方向(建议使用 orientation) |
vertical | boolean | false | 排列方向,快捷设为垂直 |
lazy | boolean | false | 延迟渲染模式,拖拽松手才更新 |
draggerIcon | string | VNode | Component | null | 默认把手图标 | 拖拽图标,传 null 隐藏 |
collapsible | { motion?: boolean; icon?: { start?: VueNode; end?: VueNode } } | - | motion 折叠动画(默认开启),icon 自定义折叠图标 |
destroyOnHidden | boolean | false | 折叠时(size 为 0)销毁面板内容,可在单个面板上覆盖 |
classNames | SplitterSemantic | - | 语义化结构类名:root / panel / dragger(支持 { default, active }) |
styles | SplitterSemanticStyles | - | 语义化结构行内样式 |
| 事件 | 说明 | 回调参数 |
|---|
| resize | 面板大小变化 | (sizes: PanelSize[]) => void |
| resizeStart | 开始拖拽 | (sizes: PanelSize[]) => void |
| resizeEnd | 拖拽结束 | (sizes: PanelSize[]) => void |
| draggerDoubleClick | 双击拖拽条 | (index: number) => void |
| collapse | 折叠/展开 | (collapsed: boolean[], sizes: PanelSize[]) => void |
| 属性 | 类型 | 默认值 | 说明 |
|---|
defaultSize | number | string | "1fr" | 初始面板大小 |
size | number | string | - | 受控面板大小 |
min | number | string | - | 最小阈值 |
max | number | string | - | 最大阈值 |
resizable | boolean | true | 是否开启拖拽伸缩 |
collapsible | boolean | { start?: boolean; end?: boolean; showCollapsibleIcon?: boolean | "auto" } | false | 是否可折叠:start 在面板起始边拖拽条显示折叠按钮,end 在面板结束边拖拽条显示折叠按钮,showCollapsibleIcon 控制图标显示方式 |
destroyOnHidden | boolean | - | 折叠时销毁面板内容,覆盖 Splitter 同名属性 |
class | string | - | 自定义样式类 |
type PanelSize = number | string; // 数字为 px,字符串支持 "50%" 等