Resizable 可调面板
通过可拖拽的分隔线构建灵活的可调整大小面板布局。
| 名称 | 分类 | 说明 | 类型 | 默认值 |
|---|---|---|---|---|
default-size | 尺寸 | 面板初始大小(百分比 1-100),未设置时自动分配剩余空间 | number | — |
min-size | 尺寸 | 面板最小大小(百分比) | number | 10 |
max-size | 尺寸 | 面板最大大小(百分比) | number | 100 |
collapsed-size | 尺寸 | 折叠后的面板大小(百分比) | number | 0 |
disabled | 状态 | 是否禁用拖拽 | boolean | false |
direction | 行为 | 面板排列方向 | 'horizontal' | 'vertical' | — |
auto-save-id | 行为 | 自动保存布局的唯一标识,设置后布局会持久化到 localStorage | string | — |
keyboard-resize-by | 行为 | 键盘方向键调整面板大小的步长(百分比) | number | 10 |
collapsible | 行为 | 是否可折叠 | boolean | false |
hit-area-margins | 行为 | 增加手柄的可交互区域(像素) | number | 0 |
layout | 事件 | 面板尺寸变化时触发,参数为各面板的百分比大小数组 | (sizes: number[]) => void | — |
resize | 事件 | 面板大小变化时触发 | (size: number) => void | — |
collapse | 事件 | 面板折叠时触发 | () => void | — |
expand | 事件 | 面板展开时触发 | () => void | — |
dragging | 事件 | 拖拽状态变化时触发 | (isDragging: boolean) => void | — |
default | 插槽 | ResizablePanel 和 ResizableHandle 组件 | — | |
default | 插槽 | 面板内容 | — | |
collapse | 暴露 | 折叠面板 | () => void | — |
expand | 暴露 | 展开面板 | () => void | — |
getSize | 暴露 | 获取当前面板大小 | () => number | — |
resize | 暴露 | 设置面板大小 | (size: number) => void | — |
基础用法
水平双面板布局,拖动手柄调整大小。
<template>
<div class="demo-resizable">
<px-resizable-group direction="horizontal">
<px-resizable-panel :default-size="50">
<div class="demo-panel">Panel A</div>
</px-resizable-panel>
<px-resizable-handle />
<px-resizable-panel :default-size="50">
<div class="demo-panel">Panel B</div>
</px-resizable-panel>
</px-resizable-group>
</div>
</template>
<style scoped>
.demo-resizable {
height: 200px;
border: 2px solid var(--px-border-color);
}
.demo-panel {
display: flex;
align-items: center;
justify-content: center;
height: 100%;
font-family: var(--px-font-family);
}
</style>垂直方向
使用 direction="vertical" 实现上下分割。
<template>
<div class="demo-resizable">
<px-resizable-group direction="vertical">
<px-resizable-panel :default-size="40">
<div class="demo-panel">Top</div>
</px-resizable-panel>
<px-resizable-handle />
<px-resizable-panel :default-size="60">
<div class="demo-panel">Bottom</div>
</px-resizable-panel>
</px-resizable-group>
</div>
</template>
<style scoped>
.demo-resizable {
height: 300px;
border: 2px solid var(--px-border-color);
}
.demo-panel {
display: flex;
align-items: center;
justify-content: center;
height: 100%;
font-family: var(--px-font-family);
}
</style>三面板布局
多个面板之间用手柄分隔。
<template>
<div class="demo-resizable">
<px-resizable-group direction="horizontal">
<px-resizable-panel :default-size="25">
<div class="demo-panel">Sidebar</div>
</px-resizable-panel>
<px-resizable-handle />
<px-resizable-panel :default-size="50">
<div class="demo-panel">Content</div>
</px-resizable-panel>
<px-resizable-handle />
<px-resizable-panel :default-size="25">
<div class="demo-panel">Inspector</div>
</px-resizable-panel>
</px-resizable-group>
</div>
</template>
<style scoped>
.demo-resizable {
height: 200px;
border: 2px solid var(--px-border-color);
}
.demo-panel {
display: flex;
align-items: center;
justify-content: center;
height: 100%;
font-family: var(--px-font-family);
}
</style>最小/最大尺寸
使用 min-size 和 max-size 约束面板大小。
<template>
<div class="demo-resizable">
<px-resizable-group direction="horizontal">
<px-resizable-panel :default-size="30" :min-size="20" :max-size="50">
<div class="demo-panel">Min 20% / Max 50%</div>
</px-resizable-panel>
<px-resizable-handle />
<px-resizable-panel :default-size="70">
<div class="demo-panel">Flexible</div>
</px-resizable-panel>
</px-resizable-group>
</div>
</template>
<style scoped>
.demo-resizable {
height: 200px;
border: 2px solid var(--px-border-color);
}
.demo-panel {
display: flex;
align-items: center;
justify-content: center;
height: 100%;
font-family: var(--px-font-family);
font-size: 12px;
}
</style>可折叠面板
设置 collapsible 允许面板折叠到 collapsed-size。通过暴露的 collapse() 和 expand() 方法控制。
<script setup lang="ts">
import { ref } from 'vue';
const panelRef = ref();
function toggleCollapse() {
if (!panelRef.value) return;
if (panelRef.value.getSize() <= 5) {
panelRef.value.expand();
} else {
panelRef.value.collapse();
}
}
</script>
<template>
<px-button @click="toggleCollapse" style="margin-bottom: 12px">
Toggle Sidebar
</px-button>
<div class="demo-resizable">
<px-resizable-group direction="horizontal">
<px-resizable-panel
ref="panelRef"
:default-size="30"
collapsible
:collapsed-size="0"
>
<div class="demo-panel">Sidebar</div>
</px-resizable-panel>
<px-resizable-handle />
<px-resizable-panel :default-size="70">
<div class="demo-panel">Content</div>
</px-resizable-panel>
</px-resizable-group>
</div>
</template>
<style scoped>
.demo-resizable {
height: 200px;
border: 2px solid var(--px-border-color);
}
.demo-panel {
display: flex;
align-items: center;
justify-content: center;
height: 100%;
font-family: var(--px-font-family);
}
</style>嵌套布局
嵌套不同方向的 ResizableGroup 组件实现复杂布局。
<template>
<div class="demo-resizable">
<px-resizable-group direction="vertical">
<px-resizable-panel :default-size="60">
<px-resizable-group direction="horizontal">
<px-resizable-panel :default-size="30">
<div class="demo-panel">Sidebar</div>
</px-resizable-panel>
<px-resizable-handle />
<px-resizable-panel :default-size="70">
<div class="demo-panel">Editor</div>
</px-resizable-panel>
</px-resizable-group>
</px-resizable-panel>
<px-resizable-handle />
<px-resizable-panel :default-size="40">
<div class="demo-panel">Terminal</div>
</px-resizable-panel>
</px-resizable-group>
</div>
</template>
<style scoped>
.demo-resizable {
height: 350px;
border: 2px solid var(--px-border-color);
}
.demo-panel {
display: flex;
align-items: center;
justify-content: center;
height: 100%;
font-family: var(--px-font-family);
}
</style>自动保存
设置 auto-save-id 将布局持久化到 localStorage,刷新页面后自动恢复。
<template>
<div class="demo-resizable">
<p style="margin-bottom: 8px; font-family: var(--px-font-family)">
Resize the panels, then reload the page — the layout is saved.
</p>
<div class="demo-container">
<px-resizable-group direction="horizontal" auto-save-id="demo-layout">
<px-resizable-panel :default-size="40">
<div class="demo-panel">Saved Panel A</div>
</px-resizable-panel>
<px-resizable-handle />
<px-resizable-panel :default-size="60">
<div class="demo-panel">Saved Panel B</div>
</px-resizable-panel>
</px-resizable-group>
</div>
</div>
</template>
<style scoped>
.demo-container {
height: 200px;
border: 2px solid var(--px-border-color);
}
.demo-panel {
display: flex;
align-items: center;
justify-content: center;
height: 100%;
font-family: var(--px-font-family);
}
</style>