fix(components): [splitter] collapse works with two-way size and min & max (#21738)

* fix(components): [splitter] collapse works with two-way size and min

* test: fix case

* chore: rerun ci
This commit is contained in:
Zhong
2025-08-16 01:18:31 +08:00
committed by GitHub
parent cf28d96966
commit a2884da5f8
2 changed files with 57 additions and 5 deletions

View File

@@ -1,4 +1,4 @@
import { nextTick } from 'vue'
import { nextTick, ref } from 'vue'
import { mount } from '@vue/test-utils'
import { afterAll, beforeAll, describe, expect, it, vi } from 'vitest'
import { ElSplitter, ElSplitterPanel } from '../index'
@@ -217,4 +217,56 @@ describe('Splitter', () => {
await nextTick()
expect(onCollapse).toHaveBeenCalledWith(0, 'end', [200, 200])
})
it('should collapse normally when size is two-way bound and min & max is set', async () => {
const size = ref(150)
const wrapper = mount(() => (
<div style={{ width: '400px', height: '400px' }}>
<ElSplitter>
<ElSplitterPanel
v-model:size={size.value}
collapsible
min={50}
max={200}
>
Left Panel
</ElSplitterPanel>
<ElSplitterPanel collapsible>Right Panel</ElSplitterPanel>
</ElSplitter>
</div>
))
await nextTick()
const panels = wrapper.findAll('.el-splitter-panel')
const startCollapseButton = wrapper.find(
'.el-splitter-bar__horizontal-collapse-icon-start'
)
const endCollapseButton = wrapper.find(
'.el-splitter-bar__horizontal-collapse-icon-end'
)
// default size
expect(panels[0].attributes('style')).toContain('flex-basis: 150px;')
// Click collapse button
await startCollapseButton.trigger('click')
await nextTick()
// Panel should be collapsed (size = 0)
expect(panels[0].attributes('style')).toContain('flex-basis: 0px;')
// Click collapse button to expand
await endCollapseButton.trigger('click')
await nextTick()
// Panel should be restored to original size
expect(panels[0].attributes('style')).toContain('flex-basis: 150px;')
// Click collapse button to expand
await endCollapseButton.trigger('click')
await nextTick()
// Panel should be collapsed (size = 400)
expect(panels[0].attributes('style')).toContain('flex-basis: 400px;')
})
})

View File

@@ -115,7 +115,7 @@ let isSizeUpdating = false
watch(
() => props.size,
() => {
if (panel.value) {
if (!isSizeUpdating && panel.value) {
const size = sizeToPx(props.size)
const maxSize = sizeToPx(props.max)
const minSize = sizeToPx(props.min)
@@ -124,12 +124,10 @@ watch(
const finalSize = Math.min(Math.max(size, minSize || 0), maxSize || size)
if (finalSize !== size) {
isSizeUpdating = true
emits('update:size', finalSize)
}
panel.value.size = finalSize
nextTick(() => (isSizeUpdating = false))
}
}
)
@@ -137,8 +135,10 @@ watch(
watch(
() => panel.value?.size,
(val) => {
if (!isSizeUpdating && val !== props.size) {
if (val !== props.size) {
isSizeUpdating = true
emits('update:size', val as number)
nextTick(() => (isSizeUpdating = false))
}
}
)