Skip to content

Commit 5e72b36

Browse files
committed
fix(list-scroll): supports scroll boundary
1 parent c24c8ac commit 5e72b36

File tree

1 file changed

+30
-12
lines changed

1 file changed

+30
-12
lines changed

src/components/common/list/ListScroll.vue

+30-12
Original file line numberDiff line numberDiff line change
@@ -77,6 +77,11 @@ const props = defineProps({
7777
required: false,
7878
default: 300,
7979
},
80+
scrollBoundary: {
81+
type: Number,
82+
required: false,
83+
default: 0,
84+
},
8085
showProgress: {
8186
type: Boolean,
8287
required: false,
@@ -117,25 +122,46 @@ defineExpose({
117122
list: listRef,
118123
});
119124
120-
const { items, loading, pagination, scrollThreshold, listOptions, backdrop, hidePoster } =
121-
toRefs(props);
125+
const {
126+
items,
127+
loading,
128+
pagination,
129+
scrollThreshold,
130+
listOptions,
131+
backdrop,
132+
hidePoster,
133+
scrollBoundary,
134+
} = toRefs(props);
122135
123136
const scrolled = ref(false);
124137
138+
const isCompact = watchMedia('(max-width: 600px)');
139+
const showBackdrop = computed(() => backdrop?.value && !isCompact.value);
140+
141+
const isTiny = watchMedia('(max-width: 350px)');
142+
const showPoster = computed(() => !hidePoster?.value && !isTiny.value);
143+
144+
const defaultSize = computed(() => (showPoster.value ? 145 : 130));
145+
const listItemSize = computed(() => listOptions?.value?.itemSize ?? defaultSize.value);
146+
const scrollBoundarySize = computed(
147+
() => (scrollBoundary?.value ?? 0) * listItemSize.value,
148+
);
149+
125150
const onScrollHandler = async (e: Event) => {
126151
if (loading.value) return;
127152
if (!e?.target) return;
128153
const { scrollTop, scrollHeight, clientHeight } = e.target as HTMLElement;
129154
if (scrollHeight === clientHeight) return;
130-
if (!scrollTop) {
155+
if (!scrollTop || scrollTop < scrollBoundarySize.value) {
131156
scrolled.value = false;
132157
return emits('onScrollTop', listRef);
133158
}
134159
if (!scrolled.value && scrollTop > scrollThreshold.value) {
135160
emits('onScroll', listRef);
136161
scrolled.value = true;
137162
}
138-
if (scrollHeight !== scrollTop + clientHeight) return;
163+
const scrollBottom = scrollTop + clientHeight + scrollBoundarySize.value;
164+
if (scrollHeight > scrollBottom) return;
139165
if (pagination?.value && pagination?.value?.page === pagination?.value?.pageCount) {
140166
return;
141167
}
@@ -156,8 +182,6 @@ const onLoadMore = (payload: { page: number; pageCount: number; pageSize: number
156182
};
157183
158184
const isEmpty = computed(() => !items.value.length && !loading.value);
159-
const defaultSize = computed(() => (hidePoster.value ? 130 : 145));
160-
const listItemSize = computed(() => listOptions?.value?.itemSize ?? defaultSize.value);
161185
162186
const topInset = computed(() => {
163187
const listElementRef = listRef.value?.$el;
@@ -172,12 +196,6 @@ const listPaddingTop = computed(
172196
() => topInset.value + (listOptions?.value?.paddingTop ?? 60),
173197
);
174198
const listPaddingBottom = computed(() => listOptions?.value?.paddingBottom ?? 32);
175-
176-
const isCompact = watchMedia('(max-width: 600px)');
177-
const showBackdrop = computed(() => backdrop?.value && !isCompact.value);
178-
179-
const isTiny = watchMedia('(max-width: 350px)');
180-
const showPoster = computed(() => !hidePoster?.value && !isTiny.value);
181199
</script>
182200

183201
<template>

0 commit comments

Comments
 (0)