diff --git a/src/App.vue b/src/App.vue index a1558b3..5c495c5 100644 --- a/src/App.vue +++ b/src/App.vue @@ -1,5 +1,10 @@ @@ -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; +} diff --git a/src/components/SplitLayout.vue b/src/components/SplitLayout.vue index d74f367..617b116 100644 --- a/src/components/SplitLayout.vue +++ b/src/components/SplitLayout.vue @@ -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 })), + ) + } + }, }) /** diff --git a/src/components/SplitPanel.vue b/src/components/SplitPanel.vue index d92cac2..c735adc 100644 --- a/src/components/SplitPanel.vue +++ b/src/components/SplitPanel.vue @@ -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) + } + }, +)