feat(面板尺寸): 添加面板尺寸动态更新功能
在SplitLayout组件中添加updatePaneSize方法,用于在外部size属性变化时更新面板尺寸。SplitPanel组件通过watch监听size属性变化,调用父组件的updatePaneSize方法实现尺寸同步。App.vue中添加输入控件,演示面板尺寸的双向绑定功能。
This commit is contained in:
parent
dfd3d962c7
commit
62fe6810a7
63
src/App.vue
63
src/App.vue
@ -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>
|
||||
|
@ -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 })),
|
||||
)
|
||||
}
|
||||
},
|
||||
})
|
||||
|
||||
/**
|
||||
|
@ -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>
|
||||
|
Loading…
x
Reference in New Issue
Block a user