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">
|
<script setup lang="ts">
|
||||||
|
import { ref } from 'vue'
|
||||||
import { SplitLayout, SplitPanel } from './components'
|
import { SplitLayout, SplitPanel } from './components'
|
||||||
|
|
||||||
|
// 用于演示双向绑定的面板尺寸状态
|
||||||
|
const leftPanelSize = ref(30)
|
||||||
|
const rightPanelSize = ref(30)
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<template>
|
<template>
|
||||||
@ -75,6 +80,38 @@ import { SplitLayout, SplitPanel } from './components'
|
|||||||
</SplitPanel>
|
</SplitPanel>
|
||||||
</SplitLayout>
|
</SplitLayout>
|
||||||
</div>
|
</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>
|
</div>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
@ -114,4 +151,30 @@ h2 {
|
|||||||
margin-bottom: 10px;
|
margin-bottom: 10px;
|
||||||
color: #1890ff;
|
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>
|
</style>
|
||||||
|
@ -94,6 +94,29 @@ provide('splitter-context', {
|
|||||||
panes.value.splice(index, 1)
|
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的子组件,表示一个可调整大小的面板。
|
* 该组件作为SplitLayout的子组件,表示一个可调整大小的面板。
|
||||||
* 通过provide/inject机制与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({
|
const props = defineProps({
|
||||||
@ -51,6 +51,7 @@ const splitterContext = inject('splitter-context') as {
|
|||||||
panes: { value: Array<{ id: string; size: number; minSize: number; maxSize: number }> }
|
panes: { value: Array<{ id: string; size: number; minSize: number; maxSize: number }> }
|
||||||
registerPane: (id: string, size: number, minSize: number, maxSize: number) => number
|
registerPane: (id: string, size: number, minSize: number, maxSize: number) => number
|
||||||
unregisterPane: (index: number) => void
|
unregisterPane: (index: number) => void
|
||||||
|
updatePaneSize: (index: number, newSize: number) => void
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -97,6 +98,20 @@ onBeforeUnmount(() => {
|
|||||||
// 注销面板,传入索引值
|
// 注销面板,传入索引值
|
||||||
splitterContext.unregisterPane(paneIndex.value)
|
splitterContext.unregisterPane(paneIndex.value)
|
||||||
})
|
})
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 监听size属性变化
|
||||||
|
* 当外部组件修改size值时,调用父组件的updatePaneSize方法更新面板尺寸
|
||||||
|
*/
|
||||||
|
watch(
|
||||||
|
() => props.size,
|
||||||
|
(newSize) => {
|
||||||
|
// 只有当面板已注册且size值有效时才更新
|
||||||
|
if (paneIndex.value >= 0 && newSize > 0) {
|
||||||
|
splitterContext.updatePaneSize(paneIndex.value, newSize)
|
||||||
|
}
|
||||||
|
},
|
||||||
|
)
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<template>
|
<template>
|
||||||
|
Loading…
x
Reference in New Issue
Block a user