Splitter 分隔面板

自由切分区域,支持拖拽调整与折叠

何时使用

  • 需要将页面区域自由切分为多个可拖拽调整的面板时。
  • 需要水平或垂直布局、面板折叠等功能时。
  • 构建 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>

API

Splitter Props

属性类型默认值说明
orientation"horizontal" | "vertical"-布局方向(与 vertical 同时存在时优先)
layout"horizontal" | "vertical""horizontal"布局方向(建议使用 orientation)
verticalbooleanfalse排列方向,快捷设为垂直
lazybooleanfalse延迟渲染模式,拖拽松手才更新
draggerIconstring | VNode | Component | null默认把手图标拖拽图标,传 null 隐藏
collapsible{ motion?: boolean; icon?: { start?: VueNode; end?: VueNode } }-motion 折叠动画(默认开启),icon 自定义折叠图标
destroyOnHiddenbooleanfalse折叠时(size 为 0)销毁面板内容,可在单个面板上覆盖
classNamesSplitterSemantic-语义化结构类名:root / panel / dragger(支持 { default, active })
stylesSplitterSemanticStyles-语义化结构行内样式

Splitter Events

事件说明回调参数
resize面板大小变化(sizes: PanelSize[]) => void
resizeStart开始拖拽(sizes: PanelSize[]) => void
resizeEnd拖拽结束(sizes: PanelSize[]) => void
draggerDoubleClick双击拖拽条(index: number) => void
collapse折叠/展开(collapsed: boolean[], sizes: PanelSize[]) => void

SplitterPanel Props

属性类型默认值说明
defaultSizenumber | string"1fr"初始面板大小
sizenumber | string-受控面板大小
minnumber | string-最小阈值
maxnumber | string-最大阈值
resizablebooleantrue是否开启拖拽伸缩
collapsibleboolean | { start?: boolean; end?: boolean; showCollapsibleIcon?: boolean | "auto" }false是否可折叠:start 在面板起始边拖拽条显示折叠按钮,end 在面板结束边拖拽条显示折叠按钮,showCollapsibleIcon 控制图标显示方式
destroyOnHiddenboolean-折叠时销毁面板内容,覆盖 Splitter 同名属性
classstring-自定义样式类

PanelSize

type PanelSize = number | string; // 数字为 px,字符串支持 "50%" 等