Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat(list): support scrollTo API to scroll to a specified element #4863

Merged
merged 4 commits into from
Dec 25, 2024
Merged
Show file tree
Hide file tree
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
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;
uyarn marked this conversation as resolved.
Show resolved Hide resolved
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
Loading