feat: 1.优化了miaoDirectory中多选的性能表现。2.图片浏览组件新增拖入虚拟文件/文件夹相关处理

This commit is contained in:
539943419 committed 2024-08-30 20:58:18 +08:00
1 parent 704c80e019
commit 7574acdad2
3 files changed
+83 -18

No files matched your search

+54 -8
View File
@@ -1,3 +1,5 @@
<!-- 只适合用于渲染过程较为复杂的组件,不然可能得不偿失
这么泛用的组件,性能差点也能理解 -->
<template> <template>
<div class="miao-lazy" ref="miaoLazyRoot" :style="!show ? { minHeight, minWidth } : {}"> <div class="miao-lazy" ref="miaoLazyRoot" :style="!show ? { minHeight, minWidth } : {}">
<slot v-if="show" /> <slot v-if="show" />
@@ -5,13 +7,14 @@
</template> </template>
<script setup lang="ts"> <script setup lang="ts">
import { onMounted, ref } from 'vue'; import { onBeforeUnmount, onMounted, ref } from 'vue';
const props = defineProps({ const props = defineProps({
show: { disableLazy: {
type: Boolean, type: Boolean,
default: false, default: false,
}, },
// 仅在内容未加载时生效,用于占位
minHeight: { minHeight: {
type: String, type: String,
default: 'none', default: 'none',
@@ -24,26 +27,69 @@ const props = defineProps({
const miaoLazyRoot = ref<HTMLDivElement>() const miaoLazyRoot = ref<HTMLDivElement>()
const show = ref<boolean>(props.show === true) const show = ref<boolean>(props.disableLazy)
const isVisible = (dom: HTMLDivElement) => {
const offset = dom.getBoundingClientRect().top
return offset > 0 && offset < 2000
}
const { showSlot, hideSlot, clearTimer } = (() => {
let timer: any
let timerInterval: any
const clearTimer = () => {
timer && clearTimeout(timer)
timerInterval && clearInterval(timerInterval)
timer = undefined
timerInterval = undefined
}
const hideSlot = () => {
clearTimer()
show.value = false
}
const showSlot = () => {
if (show.value === true) {
return
}
clearTimer()
// timer = setTimeout(() => {
if (!miaoLazyRoot.value || isVisible(miaoLazyRoot.value) === false) {
return
}
show.value = true
timerInterval = setInterval(() => {
if (show.value === false || miaoLazyRoot.value === undefined) {
return
}
if (isVisible(miaoLazyRoot.value) === false) {
hideSlot()
}
}, 1000)
// })
}
return { showSlot, hideSlot, clearTimer }
})()
onMounted(() => { onMounted(() => {
if (show.value === false) { if (show.value === false) {
let options = { let options = {
root: null, // 默认为视窗 threshold: 0
rootMargin: '0px', // 视窗的外边距
threshold: 0.1 // 目标元素可见比例达到 10% 时触发回调
}; };
let observer: IntersectionObserver | undefined = new IntersectionObserver((entries) => { let observer: IntersectionObserver | undefined = new IntersectionObserver((entries) => {
if (entries[0].isIntersecting) { if (entries[0].isIntersecting) {
show.value = true showSlot()
// miaoLazyRoot.value && observer?.unobserve(miaoLazyRoot.value) // miaoLazyRoot.value && observer?.unobserve(miaoLazyRoot.value)
// observer = undefined // observer = undefined
} else { } else {
show.value = false hideSlot()
} }
}, options); }, options);
miaoLazyRoot.value && observer.observe(miaoLazyRoot.value); miaoLazyRoot.value && observer.observe(miaoLazyRoot.value);
} }
}) })
onBeforeUnmount(() => {
clearTimer()
})
</script> </script>
+9 -6
View File
@@ -42,8 +42,8 @@
}"> }">
<n-scrollbar ref="scrollbarRef"> <n-scrollbar ref="scrollbarRef">
<transition-group name="dirItem"> <transition-group name="dirItem">
<miao-lazy-div v-for="(dir, index) in showData_directory" :key="dir.uid" :show="index < 20" <miao-lazy-div v-for="(dir, index) in showData_directory" :key="dir.uid"
min-height="50px"> :disableLazy="index < 20" min-height="50px">
<miaoDirectoryItem :item="dir" :color="props.color" :selectedItem="selectedItem.value" <miaoDirectoryItem :item="dir" :color="props.color" :selectedItem="selectedItem.value"
@delete="handleItemDelete(dir)" @click="handleItemClick(dir)" @delete="handleItemDelete(dir)" @click="handleItemClick(dir)"
@drag-start="handleItemDragStart" @rename="handleItemRename(dir)" @drag-start="handleItemDragStart" @rename="handleItemRename(dir)"
@@ -51,7 +51,7 @@
</miao-lazy-div> </miao-lazy-div>
</transition-group> </transition-group>
<transition-group name="dirItem"> <transition-group name="dirItem">
<miao-lazy-div v-for="(file, index) in showData_files" :key="file.uid" :show="index < 20" <miao-lazy-div v-for="(file, index) in showData_files" :key="file.uid" :disableLazy="index < 20"
min-height="50px"> min-height="50px">
<miaoDirectoryItem :item="file" :color="props.color" :selectedItem="selectedItem.value" <miaoDirectoryItem :item="file" :color="props.color" :selectedItem="selectedItem.value"
@click="handleItemClick(file)" @download="handleItemDownload(file)" @click="handleItemClick(file)" @download="handleItemDownload(file)"
@@ -158,12 +158,13 @@ class SelectedItem {
} }
// 保证内容仍然存在于dir中且各个元素不重复 // 保证内容仍然存在于dir中且各个元素不重复
get value() { get value() {
const _filterList = [...(currentDirectory.value?.directories ?? []), ...(currentDirectory.value?.files ?? [])]
return uniq(this._selectedItem).filter(v => { return uniq(this._selectedItem).filter(v => {
if (currentDirectory.value === undefined) { if (currentDirectory.value === undefined) {
return false return false
} }
// @ts-ignore // @ts-ignore
return [...currentDirectory.value?.directories, ...currentDirectory.value?.files].includes(v) return _filterList.includes(v)
}) })
} }
} }
@@ -221,8 +222,8 @@ const setCurrentDirectory = async (virtualDirectory: VirtualDirectory) => {
} else { } else {
virtualDirectory.update() virtualDirectory.update()
} }
currentDirectories.value[0] !== virtualDirectory && selectedItem.clear() if (currentDirectories.value[0] !== virtualDirectory) {
currentDirectories.value[0] = virtualDirectory selectedItem.clear()
nextTick(() => { nextTick(() => {
scrollbarRef.value.scrollTo({ scrollbarRef.value.scrollTo({
top: 0, top: 0,
@@ -230,6 +231,8 @@ const setCurrentDirectory = async (virtualDirectory: VirtualDirectory) => {
}) })
}) })
} }
currentDirectories.value[0] = virtualDirectory
}
const reload = () => { const reload = () => {
setCurrentDirectory(currentDirectory.value) setCurrentDirectory(currentDirectory.value)
+20 -4
View File
@@ -1,30 +1,33 @@
<template> <template>
<miao-drop-handler @on-virtual-directory="handleDrop" @on-virtual-files="handleDrop">
<div class="miaoImage" ref="rootRef"> <div class="miaoImage" ref="rootRef">
<n-scrollbar ref="NScrollbarRef"> <n-scrollbar ref="NScrollbarRef">
<div class="miaoImage-container"> <div class="miaoImage-container">
<div class="miaoImage-container-row" v-for="(src, index) in imageSrcList" :key="index"> <div class="miaoImage-container-row" v-for="(src, index) in imageSrcList" :key="index">
<img :src="src" class="miaoImage-container-row-image" loading="lazy" <img :src="src" class="miaoImage-container-row-image" loading="lazy"
:class="activeImageIndex === index ? 'miaoImage-container-row-image-active' : ''" :class="activeImageIndex === index ? 'miaoImage-container-row-image-active' : ''"
@click="activeImageIndex = index" draggable="false" /> @click="activeImageIndex = index" />
</div> </div>
</div> </div>
</n-scrollbar> </n-scrollbar>
<miao-mask :show="activeImageIndex !== -1" @click="activeImageIndex = -1" class="miaoImage-mask"> <miao-mask :show="activeImageIndex !== -1" @click="activeImageIndex = -1" class="miaoImage-mask">
<ChevronBack class="miaoImage-mask-btn miaoImage-mask-btn-back" @click="handleActiveImageIndexBack" /> <ChevronBack class="miaoImage-mask-btn miaoImage-mask-btn-back" @click="handleActiveImageIndexBack" />
<img :src="imageSrcList[activeImageIndex]" class="miaoImage-mask-active" @click="e => e.stopPropagation()" <img :src="imageSrcList[activeImageIndex]" class="miaoImage-mask-active"
draggable="false"> @click="e => e.stopPropagation()" draggable="false">
<ChevronForward class="miaoImage-mask-btn miaoImage-mask-btn-forward" <ChevronForward class="miaoImage-mask-btn miaoImage-mask-btn-forward"
@click="handleActiveImageIndexForward" /> @click="handleActiveImageIndexForward" />
</miao-mask> </miao-mask>
</div> </div>
</miao-drop-handler>
</template> </template>
<script setup lang="ts"> <script setup lang="ts">
import miaoMask from '@/components/miaoMask.vue';
import miaoDropHandler from '@/components/miaoDropHandler.vue';
import VirtualDirectory, { VirtualFile } from '@/class/VirtualDirectory' import VirtualDirectory, { VirtualFile } from '@/class/VirtualDirectory'
import { uniq } from 'lodash'; import { uniq } from 'lodash';
import { nextTick, onMounted, ref } from 'vue' import { nextTick, onMounted, ref } from 'vue'
import { NScrollbar } from 'naive-ui'; import { NScrollbar } from 'naive-ui';
import miaoMask from '@/components/miaoMask.vue';
import { ChevronBack, ChevronForward } from '@vicons/ionicons5' import { ChevronBack, ChevronForward } from '@vicons/ionicons5'
const imageSuffixList = [ const imageSuffixList = [
@@ -82,6 +85,19 @@ const handleActiveImageIndexForward = (e: any) => {
nextTick(scrollToActiveImage) nextTick(scrollToActiveImage)
} }
const handleDrop = (vItems: (VirtualFile | VirtualDirectory)[]) => {
if (vItems[0].type === 'directory') {
// @ts-ignore
currentDirectories.value = [...currentDirectories.value, ...vItems]
} else {
// @ts-ignore
currentFiles.value = [...currentFiles, ...vItems]
}
vItems.forEach(v => {
updateImageSrcList(v)
})
}
const updateImageSrcList = async (source: VirtualFile | VirtualDirectory) => { const updateImageSrcList = async (source: VirtualFile | VirtualDirectory) => {
let srcList: string[] let srcList: string[]
if (source.type === 'directory') { if (source.type === 'directory') {