优化参数配置,简化组件构建

This commit is contained in:
2024-12-11 15:40:44 +08:00
parent 812a642aaa
commit 0a8af1d97b
4 changed files with 31 additions and 51 deletions

View File

@@ -1,6 +1,6 @@
<script setup lang="ts">
import ProjectList from './components/ProjectList.vue'
import type { ListItem, MenuItem, ListConfig } from '@/types'
import type { ListItem, MenuItem } from '@/types'
// 生成模拟数据
const listData: ListItem[] = Array.from({ length: 789 }, (_, i) => ({
@@ -15,14 +15,6 @@ const listData: ListItem[] = Array.from({ length: 789 }, (_, i) => ({
]
}))
// 自定义配置
const listConfig: ListConfig = {
itemHeight: 50,
itemPadding: 16,
bufferCount: 10,
scrollDebounceTime: 16,
}
// 自定义菜单项
const menuItems: MenuItem[] = [
{
@@ -57,10 +49,7 @@ const handleItemClick = (item: ListItem): void => {
<template>
<ProjectList
:data="listData"
:config="listConfig"
:menu-items="menuItems"
:show-toolbar="true"
:toolbar-height="40"
@click="handleItemClick"
/>
</template>

View File

@@ -1,7 +1,7 @@
<script setup lang="ts">
import VirtualList from './VirtualList.vue'
import { ref, onMounted, onBeforeUnmount } from 'vue'
import type { ListItem, MenuItem, ListConfig } from '@/types'
import type { ListItem, MenuItem } from '@/types'
/**
* 组件属性接口
@@ -9,20 +9,17 @@ import type { ListItem, MenuItem, ListConfig } from '@/types'
interface Props {
/** 列表数据 */
data: ListItem[]
/** 虚拟列表配置 */
config: ListConfig
/** 菜单项配置 */
menuItems: MenuItem[]
/** 是否显示工具栏 */
showToolbar?: boolean
/** 工具栏高度 */
toolbarHeight?: number
}
const props = withDefaults(defineProps<Props>(), {
showToolbar: true,
toolbarHeight: 40
})
const props = withDefaults(defineProps<Props>(), {})
// ===== 工具栏配置常量 =====
/** 是否显示工具栏 */
const SHOW_TOOLBAR = true
/** 工具栏高度(像素) */
const TOOLBAR_HEIGHT = 40
/**
* 组件事件定义
@@ -237,7 +234,6 @@ const onAfterLeave = (el: Element): void => {
<div class="main-content">
<VirtualList
:data="data"
:config="config"
:frozen="listFrozen"
:disable-hover="showMenu || temporaryDisableHover"
@select="handleSelect"
@@ -248,7 +244,7 @@ const onAfterLeave = (el: Element): void => {
</div>
<!-- 工具栏 -->
<div v-if="showToolbar" class="toolbar" :style="{ height: `${toolbarHeight}px` }">
<div v-if="SHOW_TOOLBAR" class="toolbar" :style="{ height: `${TOOLBAR_HEIGHT}px` }">
<div class="toolbar-content">
<div class="total-count"> {{ data.length }} </div>
<div class="toolbar-spacer"></div>
@@ -335,7 +331,7 @@ const onAfterLeave = (el: Element): void => {
color: #666;
}
/* 弹性间隔:用推开左右两侧的内容 */
/* 弹性间隔:用<EFBFBD><EFBFBD>推开左右两侧的内容 */
.toolbar-spacer {
flex: 1;
}

View File

@@ -1,10 +1,9 @@
<script setup lang="ts">
import { ref, computed, onMounted, onBeforeUnmount } from 'vue'
import type { ListItem, ListConfig } from '@/types'
import type { ListItem } from '@/types'
interface Props {
data: ListItem[]
config: ListConfig
height?: string | number
frozen?: boolean
disableHover?: boolean
@@ -23,9 +22,19 @@ const emit = defineEmits<{
showToast: [message: string]
}>()
// ===== 列表配置常量 =====
/** 列表项基础高度(像素) */
const ITEM_HEIGHT = 50
/** 列表项内边距总和(像素) */
const ITEM_PADDING = 16
/** 上下缓冲区域的项目数量 */
const BUFFER_COUNT = 10
/** 滚动防抖时间(毫秒) */
const SCROLL_DEBOUNCE_TIME = 16
// 计算列表项实际总高度
const totalItemHeight = computed(() =>
props.config.itemHeight + props.config.itemPadding
ITEM_HEIGHT + ITEM_PADDING
)
// 响应式状态管理
@@ -46,10 +55,10 @@ const visibleCount = computed(() =>
// 计算当前需要渲染的数据
const visibleData = computed(() => {
const visibleStart = Math.max(0, startIndex.value - props.config.bufferCount)
const visibleStart = Math.max(0, startIndex.value - BUFFER_COUNT)
const visibleEnd = Math.min(
props.data.length,
startIndex.value + visibleCount.value + props.config.bufferCount
startIndex.value + visibleCount.value + BUFFER_COUNT
)
return props.data.slice(visibleStart, visibleEnd).map((item, index) => ({
@@ -60,7 +69,7 @@ const visibleData = computed(() => {
// 计算列表偏移量
const offsetY = computed(() =>
Math.max(0, (startIndex.value - props.config.bufferCount) * totalItemHeight.value)
Math.max(0, (startIndex.value - BUFFER_COUNT) * totalItemHeight.value)
)
// 计算虚拟列表总高度
@@ -117,7 +126,7 @@ function debounce<T extends (...args: any[]) => void>(fn: T, delay: number): (..
/**
* 处理滚动事件(已防抖)
* 根据滚动位置更新可视区的起始索引
* 根据滚动位置更新可视区<EFBFBD><EFBFBD>的起始索引
*/
const handleScroll = debounce(() => {
if (!containerRef.value) return
@@ -127,7 +136,7 @@ const handleScroll = debounce(() => {
if (newStartIndex !== startIndex.value) {
startIndex.value = newStartIndex
}
}, props.config.scrollDebounceTime)
}, SCROLL_DEBOUNCE_TIME)
/** 鼠标悬停禁用状态 */
const disableHover = ref<boolean>(false)
@@ -293,7 +302,7 @@ onMounted(() => {
// 初始化容器高度
updateContainerHeight()
// 添加全局事监听
// 添加全局事<EFBFBD><EFBFBD>监听
window.addEventListener('resize', updateContainerHeight)
window.addEventListener('keydown', handleKeyDown)
})
@@ -341,7 +350,7 @@ onBeforeUnmount(() => {
:key="item.index"
class="list-item"
:class="{ 'selected': selectedIndex === item.index }"
:style="{ height: `${config.itemHeight}px` }"
:style="{ height: `${ITEM_HEIGHT}px` }"
@mouseenter="handleMouseEnter(item.index)"
@click="handleClick(item)"
@contextmenu="handleContextMenu($event, item)"

View File

@@ -37,17 +37,3 @@ export interface MenuItem {
/** 菜单项点击处理函数,接收当前选中的列表项作为参数 */
action: (item: ListItem | null) => void
}
/**
* 虚拟列表配置接口
*/
export interface ListConfig {
/** 列表项基础高度(像素) */
itemHeight: number
/** 列表项内边距总和(像素) */
itemPadding: number
/** 上下缓冲区域的项目数量 */
bufferCount: number
/** 滚动防抖时间(毫秒) */
scrollDebounceTime: number
}