mirror of
https://github.com/fugary/simple-element-plus-template.git
synced 2026-02-22 22:27:00 +00:00
opt: 优化页面分割组件split功能和样式
This commit is contained in:
@@ -1,6 +1,7 @@
|
|||||||
<script setup>
|
<script setup>
|
||||||
import { onMounted, onUnmounted, ref, useAttrs, watch } from 'vue'
|
import { onMounted, ref, useAttrs, shallowRef, watch, computed } from 'vue'
|
||||||
import Split from 'split.js'
|
import Split from 'split.js'
|
||||||
|
import { useElementSize } from '@vueuse/core'
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 更多属性配置可以参考文档
|
* 更多属性配置可以参考文档
|
||||||
@@ -38,20 +39,31 @@ const props = defineProps({
|
|||||||
default: false
|
default: false
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
|
const elementSizesRefs = ref([])
|
||||||
const itemRefs = ref([])
|
const itemRefs = ref([])
|
||||||
const isDragging = ref(false)
|
const isDragging = ref(false)
|
||||||
|
|
||||||
const attrs = useAttrs()
|
const attrs = useAttrs()
|
||||||
let splitInstance = null
|
const splitInstance = shallowRef()
|
||||||
|
|
||||||
const initSplit = () => {
|
const initSplit = () => {
|
||||||
if (splitInstance) {
|
if (splitInstance.value) {
|
||||||
splitInstance.destroy()
|
splitInstance.value.destroy()
|
||||||
splitInstance = null
|
splitInstance.value = null
|
||||||
}
|
}
|
||||||
|
// Clear previous size refs to avoid duplicates/leaks on re-init
|
||||||
|
elementSizesRefs.value = []
|
||||||
|
|
||||||
if (props.disabled) return
|
if (props.disabled) return
|
||||||
|
|
||||||
splitInstance = Split(itemRefs.value.map(itemRef => itemRef), {
|
const elements = itemRefs.value.filter(el => el)
|
||||||
|
if (elements.length === 0) return
|
||||||
|
|
||||||
|
splitInstance.value = Split(elements.map(itemRef => {
|
||||||
|
const { width, height } = useElementSize(itemRef)
|
||||||
|
elementSizesRefs.value.push(props.direction === 'vertical' ? height : width)
|
||||||
|
return itemRef
|
||||||
|
}), {
|
||||||
sizes: props.sizes,
|
sizes: props.sizes,
|
||||||
minSize: props.minSize,
|
minSize: props.minSize,
|
||||||
maxSize: props.maxSize,
|
maxSize: props.maxSize,
|
||||||
@@ -59,23 +71,31 @@ const initSplit = () => {
|
|||||||
gutterSize: 5,
|
gutterSize: 5,
|
||||||
direction: props.direction,
|
direction: props.direction,
|
||||||
...attrs,
|
...attrs,
|
||||||
|
gutter: (index, direction) => {
|
||||||
|
const gutter = document.createElement('div')
|
||||||
|
gutter.className = `gutter gutter-${direction}`
|
||||||
|
gutter.addEventListener('mousedown', () => {
|
||||||
|
gutter.classList.add('is-active')
|
||||||
|
})
|
||||||
|
return gutter
|
||||||
|
},
|
||||||
onDragStart: (sizes) => {
|
onDragStart: (sizes) => {
|
||||||
isDragging.value = true
|
isDragging.value = true
|
||||||
if (attrs.onDragStart) {
|
if (attrs.onDragStart) {
|
||||||
attrs.onDragStart(sizes)
|
attrs.onDragStart(sizes)
|
||||||
}
|
}
|
||||||
if (props.onDragStart) {
|
|
||||||
props.onDragStart(sizes)
|
|
||||||
}
|
|
||||||
},
|
},
|
||||||
onDragEnd: (sizes) => {
|
onDragEnd: (sizes) => {
|
||||||
isDragging.value = false
|
isDragging.value = false
|
||||||
|
// remove is-active from all gutters
|
||||||
|
const container = itemRefs.value[0]?.parentNode
|
||||||
|
if (container) {
|
||||||
|
container.querySelectorAll('.gutter.is-active').forEach(el => el.classList.remove('is-active'))
|
||||||
|
}
|
||||||
|
|
||||||
if (attrs.onDragEnd) {
|
if (attrs.onDragEnd) {
|
||||||
attrs.onDragEnd(sizes)
|
attrs.onDragEnd(sizes)
|
||||||
}
|
}
|
||||||
if (props.onDragEnd) {
|
|
||||||
props.onDragEnd(sizes)
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
@@ -84,27 +104,19 @@ onMounted(() => {
|
|||||||
initSplit()
|
initSplit()
|
||||||
})
|
})
|
||||||
|
|
||||||
onUnmounted(() => {
|
watch(() => props.sizes, () => {
|
||||||
if (splitInstance) {
|
initSplit()
|
||||||
splitInstance.destroy()
|
}, { flush: 'post' })
|
||||||
}
|
|
||||||
})
|
|
||||||
|
|
||||||
watch(() => props.disabled, () => {
|
watch(() => props.disabled, () => {
|
||||||
initSplit()
|
initSplit()
|
||||||
})
|
}, { flush: 'post' })
|
||||||
|
|
||||||
watch(() => props.sizes, (newSizes) => {
|
const elementSizes = computed(() => elementSizesRefs.value?.map(sizeRef => sizeRef.value))
|
||||||
if (splitInstance) {
|
|
||||||
splitInstance.setSizes(newSizes)
|
|
||||||
}
|
|
||||||
})
|
|
||||||
|
|
||||||
defineExpose({
|
defineExpose({
|
||||||
splitInstance,
|
splitInstance,
|
||||||
getSizes: () => {
|
elementSizes
|
||||||
return splitInstance ? splitInstance.getSizes() : props.sizes
|
|
||||||
}
|
|
||||||
})
|
})
|
||||||
|
|
||||||
</script>
|
</script>
|
||||||
@@ -152,7 +164,7 @@ defineExpose({
|
|||||||
background-position: 50%;
|
background-position: 50%;
|
||||||
}
|
}
|
||||||
/* Highlight when dragging (controlled by JS state) */
|
/* Highlight when dragging (controlled by JS state) */
|
||||||
.is-dragging > :deep(.gutter) {
|
:deep(.gutter.is-active) {
|
||||||
background-color: #409eff !important;
|
background-color: #409eff !important;
|
||||||
}
|
}
|
||||||
</style>
|
</style>
|
||||||
|
|||||||
Reference in New Issue
Block a user