Skip to content

Resizable 可调面板

通过可拖拽的分隔线构建灵活的可调整大小面板布局。

名称分类说明类型默认值
default-size? 尺寸面板初始大小(百分比 1-100),未设置时自动分配剩余空间number
min-size? 尺寸面板最小大小(百分比)number10
max-size? 尺寸面板最大大小(百分比)number100
collapsed-size? 尺寸折叠后的面板大小(百分比)number0
disabled? 状态是否禁用拖拽booleanfalse
direction? 行为面板排列方向'horizontal' | 'vertical'
auto-save-id? 行为自动保存布局的唯一标识,设置后布局会持久化到 localStoragestring
keyboard-resize-by? 行为键盘方向键调整面板大小的步长(百分比)number10
collapsible? 行为是否可折叠booleanfalse
hit-area-margins? 行为增加手柄的可交互区域(像素)number0
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-sizemax-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>