Skip to content

Commit

Permalink
feat(list): list组件虚拟列表支持滚动到指定元素
Browse files Browse the repository at this point in the history
提供了滚动到指定元素的示例代码

closed #4750
  • Loading branch information
naturalshen committed Dec 24, 2024
1 parent 020f13a commit 60d6131
Show file tree
Hide file tree
Showing 5 changed files with 101 additions and 29 deletions.
46 changes: 34 additions & 12 deletions src/list/_example-ts/virtual-scroll.vue
Original file line number Diff line number Diff line change
@@ -1,18 +1,40 @@
<template>
<t-list style="height: 300px" :scroll="{ type: 'virtual' }"
><t-list-item v-for="(item, index) in listRef" :key="index">
<t-list-item-meta :image="imageUrl" title="列表标题" :description="item.content" /></t-list-item
></t-list>
<t-space direction="vertical">
<t-list
ref="list"
style="height: 300px"
:scroll="{ type: 'virtual', rowHeight: 80, bufferSize: 10, threshold: 10 }"
>
<t-list-item v-for="(item, index) in listData" :key="`t${index + 1}`">
<t-list-item-meta :image="imageUrl" title="列表标题" :description="item.content" />
</t-list-item>
</t-list>
<t-space>
<t-button @click="handleScroll">滚动到指定节点</t-button>
</t-space>
</t-space>
</template>
<script lang="ts" setup>
import { ref } from 'vue';
import { ListItemMetaProps } from 'tdesign-vue-next';
const list = [];
import { ref, onMounted } from 'vue';
import { ListItemMetaProps, ListInstanceFunctions } from 'tdesign-vue-next';
const list = ref<ListInstanceFunctions>(); // 用于存储对 t-list 的引用
const listData = ref([]); // 使用 ref 来存储列表数据
const imageUrl: ListItemMetaProps['image'] = 'https://tdesign.gtimg.com/site/avatar.jpg';
for (let i = 0; i < 3000; i++) {
list.push({
content: `列表内容的描述性文字`,
onMounted(() => {
for (let i = 0; i < 3000; i++) {
listData.value.push({ content: `第${i + 1}个列表内容的描述性文字` });
}
});
const handleScroll = () => {
// scroll 属性需要设置 rowHeight 参数
list.value?.scrollTo({
// 指定key滚动,即当前节点对应的唯一值,推荐使用
key: 't30',
// 指定index滚动,如果存在多级嵌套,需要自己计算index
// index: 100,
});
}
const listRef = ref(list);
};
</script>
44 changes: 34 additions & 10 deletions src/list/_example/virtual-scroll.vue
Original file line number Diff line number Diff line change
@@ -1,16 +1,40 @@
<template>
<t-list style="height: 300px" :scroll="{ type: 'virtual' }"
><t-list-item v-for="(item, index) in listRef" :key="index">
<t-list-item-meta :image="imageUrl" title="列表标题" :description="item.content" /></t-list-item
></t-list>
<t-space direction="vertical">
<t-list
ref="list"
style="height: 300px"
:scroll="{ type: 'virtual', rowHeight: 80, bufferSize: 10, threshold: 10 }"
>
<t-list-item v-for="(item, index) in listData" :key="`t${index + 1}`">
<t-list-item-meta :image="imageUrl" title="列表标题" :description="item.content" />
</t-list-item>
</t-list>
<t-space>
<t-button @click="handleScroll">滚动到指定节点</t-button>
</t-space>
</t-space>
</template>

<script setup>
import { ref } from 'vue';
const list = [];
import { ref, onMounted } from 'vue';
const list = ref(); // 用于存储对 t-list 的引用
const listData = ref([]); // 使用 ref 来存储列表数据
const imageUrl = 'https://tdesign.gtimg.com/site/avatar.jpg';
for (let i = 0; i < 3000; i++) {
list.push({ content: `列表内容的描述性文字` });
}
const listRef = ref(list);
onMounted(() => {
for (let i = 0; i < 3000; i++) {
listData.value.push({ content: `${i + 1}个列表内容的描述性文字` });
}
});
const handleScroll = () => {
// scroll 属性需要设置 rowHeight 参数
list.value?.scrollTo({
// 指定key滚动,即当前节点对应的唯一值,推荐使用
key: 't30',
// 指定index滚动,如果存在多级嵌套,需要自己计算index
// index: 100,
});
};
</script>
22 changes: 21 additions & 1 deletion src/list/hooks/useListVirtualScroll.ts
Original file line number Diff line number Diff line change
@@ -1,7 +1,10 @@
import { Ref, computed } from 'vue';
import get from 'lodash/get';

import log from '../../_common/js/log';
import useVirtualScroll from '../../hooks/useVirtualScrollNew';
import { TdListProps } from '../type';
import { Styles } from '../../common';
import { Styles, type ComponentScrollToElementParams } from '../../common';

export const useListVirtualScroll = (
scroll: TdListProps['scroll'],
Expand Down Expand Up @@ -51,11 +54,28 @@ export const useListVirtualScroll = (
} as Styles),
);

const handleScrollTo = (params: ComponentScrollToElementParams) => {
let index = params.index;
if (!index && index !== 0) {
if (!params.key) {
log.error('List', 'scrollTo: one of `index` or `key` must exist.');
return;
}
index = listItems.value?.findIndex((item) => [get(item, 'key')].includes(params.key));
if (index < 0) {
log.error('List', `${params.key} does not exist in data, check \`key\` or \`data\` please.`);
return;
}
}
virtualConfig.scrollToElement({ ...params, index: index - 1 });
};

return {
virtualConfig,
cursorStyle,
listStyle,
isVirtualScroll,
onInnerVirtualScroll,
scrollToElement: handleScrollTo,
};
};
8 changes: 3 additions & 5 deletions src/list/list.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -26,11 +26,8 @@ export default defineComponent({
const renderTNodeJSX = useTNodeJSX();
const { listItems } = useListItems();

const { virtualConfig, cursorStyle, listStyle, isVirtualScroll, onInnerVirtualScroll } = useListVirtualScroll(
props.scroll,
listRef,
listItems,
);
const { virtualConfig, cursorStyle, listStyle, isVirtualScroll, onInnerVirtualScroll, scrollToElement } =
useListVirtualScroll(props.scroll, listRef, listItems);

/** 列表基础逻辑 start */
const listClass = computed(() => {
Expand Down Expand Up @@ -123,6 +120,7 @@ export default defineComponent({
handleLoadMore,
listRef,
isVirtualScroll,
scrollTo: scrollToElement,
};
},

Expand Down
10 changes: 9 additions & 1 deletion src/list/type.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@
* 该文件为脚本自动生成文件,请勿随意修改。如需修改请联系 PMC
* */

import { TNode, TScroll } from '../common';
import { TNode, TScroll, ComponentScrollToElementParams } from '../common';

export interface TdListProps {
/**
Expand Down Expand Up @@ -53,6 +53,14 @@ export interface TdListProps {
onScroll?: (options: { e: Event | WheelEvent; scrollTop: number; scrollBottom: number }) => void;
}

/** 组件实例方法 */
export interface ListInstanceFunctions {
/**
* 虚拟滚动场景下,支持指定滚动到具体的节点
*/
scrollTo?: (scrollToParams: ComponentScrollToElementParams) => void;
}

export interface TdListItemProps {
/**
* 操作栏
Expand Down

0 comments on commit 60d6131

Please sign in to comment.