feat(面板尺寸): 添加面板尺寸动态更新功能

在SplitLayout组件中添加updatePaneSize方法,用于在外部size属性变化时更新面板尺寸。SplitPanel组件通过watch监听size属性变化,调用父组件的updatePaneSize方法实现尺寸同步。App.vue中添加输入控件,演示面板尺寸的双向绑定功能。
This commit is contained in:
skycurtain 2025-04-03 11:05:05 +08:00
parent dfd3d962c7
commit 62fe6810a7
3 changed files with 102 additions and 1 deletions

View File

@ -1,5 +1,10 @@
<script setup lang="ts">
import { ref } from 'vue'
import { SplitLayout, SplitPanel } from './components'
//
const leftPanelSize = ref(30)
const rightPanelSize = ref(30)
</script>
<template>
@ -75,6 +80,38 @@ import { SplitLayout, SplitPanel } from './components'
</SplitPanel>
</SplitLayout>
</div>
<h2>响应式尺寸控制</h2>
<div class="control-panel">
<div class="control-item">
<label>左侧面板尺寸</label>
<input type="number" v-model="leftPanelSize" min="10" max="90" step="1" />
<span>%</span>
</div>
<div class="control-item">
<label>右侧面板尺寸</label>
<input type="number" v-model="rightPanelSize" min="10" max="90" step="1" />
<span>%</span>
</div>
</div>
<div class="demo-box">
<SplitLayout direction="horizontal">
<SplitPanel :size="leftPanelSize" :min-size="50">
<div class="SplitPanel-content">
<h3>左侧面板</h3>
<p>当前尺寸{{ leftPanelSize }}%</p>
<p>通过上方输入框修改此面板尺寸</p>
</div>
</SplitPanel>
<SplitPanel :size="rightPanelSize">
<div class="SplitPanel-content">
<h3>右侧面板</h3>
<p>当前尺寸{{ rightPanelSize }}%</p>
<p>通过上方输入框修改此面板尺寸</p>
</div>
</SplitPanel>
</SplitLayout>
</div>
</div>
</template>
@ -114,4 +151,30 @@ h2 {
margin-bottom: 10px;
color: #1890ff;
}
.control-panel {
display: flex;
gap: 20px;
margin-bottom: 15px;
background-color: #f5f5f5;
padding: 15px;
border-radius: 4px;
}
.control-item {
display: flex;
align-items: center;
gap: 8px;
}
.control-item input {
width: 60px;
padding: 5px;
border: 1px solid #d9d9d9;
border-radius: 2px;
}
.control-item label {
font-weight: 500;
}
</style>

View File

@ -94,6 +94,29 @@ provide('splitter-context', {
panes.value.splice(index, 1)
}
},
/**
* 更新面板尺寸方法
* 子组件在外部size属性变化时调用此方法更新面板尺寸
* @param index 面板在数组中的索引
* @param newSize 新的尺寸百分比
*/
updatePaneSize: (index: number, newSize: number) => {
if (index >= 0 && index < panes.value.length) {
//
const oldSize = panes.value[index].size
//
panes.value[index].size = newSize
// 100%
calculateSizes()
// resize
emit(
'resize',
panes.value.map((pane) => ({ id: pane.id, size: pane.size })),
)
}
},
})
/**

View File

@ -5,7 +5,7 @@
* 该组件作为SplitLayout的子组件表示一个可调整大小的面板
* 通过provide/inject机制与SplitLayout父组件通信实现面板的注册尺寸计算和更新
*/
import { ref, inject, computed, onMounted, onBeforeUnmount, useId } from 'vue'
import { ref, inject, computed, onMounted, onBeforeUnmount, useId, watch } from 'vue'
//
const props = defineProps({
@ -51,6 +51,7 @@ const splitterContext = inject('splitter-context') as {
panes: { value: Array<{ id: string; size: number; minSize: number; maxSize: number }> }
registerPane: (id: string, size: number, minSize: number, maxSize: number) => number
unregisterPane: (index: number) => void
updatePaneSize: (index: number, newSize: number) => void
}
/**
@ -97,6 +98,20 @@ onBeforeUnmount(() => {
//
splitterContext.unregisterPane(paneIndex.value)
})
/**
* 监听size属性变化
* 当外部组件修改size值时调用父组件的updatePaneSize方法更新面板尺寸
*/
watch(
() => props.size,
(newSize) => {
// size
if (paneIndex.value >= 0 && newSize > 0) {
splitterContext.updatePaneSize(paneIndex.value, newSize)
}
},
)
</script>
<template>