mirror of
https://github.com/nagisa77/OpenIsle.git
synced 2026-03-18 01:47:25 +08:00
feat: 通用滚动加载工具
This commit is contained in:
31
frontend/src/utils/loadMore.js
Normal file
31
frontend/src/utils/loadMore.js
Normal file
@@ -0,0 +1,31 @@
|
|||||||
|
import { ref, onMounted, onUnmounted, onActivated, nextTick } from 'vue'
|
||||||
|
|
||||||
|
export function useScrollLoadMore(loadMore, offset = 50) {
|
||||||
|
const savedScrollTop = ref(0)
|
||||||
|
|
||||||
|
const handleScroll = () => {
|
||||||
|
const scrollTop = window.scrollY || document.documentElement.scrollTop
|
||||||
|
const scrollHeight = document.documentElement.scrollHeight
|
||||||
|
const windowHeight = window.innerHeight
|
||||||
|
savedScrollTop.value = scrollTop
|
||||||
|
if (scrollHeight - (scrollTop + windowHeight) <= offset) {
|
||||||
|
loadMore()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
onMounted(() => {
|
||||||
|
window.addEventListener('scroll', handleScroll, { passive: true })
|
||||||
|
})
|
||||||
|
|
||||||
|
onUnmounted(() => {
|
||||||
|
window.removeEventListener('scroll', handleScroll)
|
||||||
|
})
|
||||||
|
|
||||||
|
onActivated(() => {
|
||||||
|
nextTick(() => {
|
||||||
|
window.scrollTo({ top: savedScrollTop.value })
|
||||||
|
})
|
||||||
|
})
|
||||||
|
|
||||||
|
return { savedScrollTop }
|
||||||
|
}
|
||||||
@@ -1,5 +1,5 @@
|
|||||||
<template>
|
<template>
|
||||||
<div ref="homePage" class="home-page" @scroll="handleScroll">
|
<div class="home-page">
|
||||||
<div v-if="!isMobile" class="search-container">
|
<div v-if="!isMobile" class="search-container">
|
||||||
<div class="search-title">一切可能,从此刻启航</div>
|
<div class="search-title">一切可能,从此刻启航</div>
|
||||||
<div class="search-subtitle">愿你在此遇见灵感与共鸣。若有疑惑,欢迎发问,亦可在知识的海洋中搜寻答案。</div>
|
<div class="search-subtitle">愿你在此遇见灵感与共鸣。若有疑惑,欢迎发问,亦可在知识的海洋中搜寻答案。</div>
|
||||||
@@ -107,8 +107,9 @@
|
|||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script>
|
<script>
|
||||||
import { ref, onMounted, watch, onActivated, nextTick } from 'vue'
|
import { ref, onMounted, watch } from 'vue'
|
||||||
import { useRoute } from 'vue-router'
|
import { useRoute } from 'vue-router'
|
||||||
|
import { useScrollLoadMore } from '../utils/loadMore'
|
||||||
import { stripMarkdown } from '../utils/markdown'
|
import { stripMarkdown } from '../utils/markdown'
|
||||||
import { API_BASE_URL } from '../main'
|
import { API_BASE_URL } from '../main'
|
||||||
import { getToken } from '../utils/auth'
|
import { getToken } from '../utils/auth'
|
||||||
@@ -134,8 +135,6 @@ export default {
|
|||||||
},
|
},
|
||||||
setup() {
|
setup() {
|
||||||
const route = useRoute()
|
const route = useRoute()
|
||||||
const homePage = ref(null)
|
|
||||||
const savedScrollTop = ref(0)
|
|
||||||
const selectedCategory = ref('')
|
const selectedCategory = ref('')
|
||||||
if (route.query.category) {
|
if (route.query.category) {
|
||||||
const c = decodeURIComponent(route.query.category)
|
const c = decodeURIComponent(route.query.category)
|
||||||
@@ -167,14 +166,6 @@ export default {
|
|||||||
const pageSize = 10
|
const pageSize = 10
|
||||||
const allLoaded = ref(false)
|
const allLoaded = ref(false)
|
||||||
|
|
||||||
onActivated(() => {
|
|
||||||
nextTick(() => {
|
|
||||||
if (homePage.value) {
|
|
||||||
homePage.value.scrollTop = savedScrollTop.value
|
|
||||||
}
|
|
||||||
})
|
|
||||||
})
|
|
||||||
|
|
||||||
// Backend now returns comment counts directly
|
// Backend now returns comment counts directly
|
||||||
|
|
||||||
const loadOptions = async () => {
|
const loadOptions = async () => {
|
||||||
@@ -366,13 +357,7 @@ export default {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
const handleScroll = (e) => {
|
useScrollLoadMore(fetchContent)
|
||||||
const el = e.target
|
|
||||||
savedScrollTop.value = el.scrollTop
|
|
||||||
if (el.scrollHeight - el.scrollTop <= el.clientHeight + 50) {
|
|
||||||
fetchContent()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
onMounted(async () => {
|
onMounted(async () => {
|
||||||
fetchContent()
|
fetchContent()
|
||||||
@@ -389,7 +374,7 @@ export default {
|
|||||||
|
|
||||||
const sanitizeDescription = (text) => stripMarkdown(text)
|
const sanitizeDescription = (text) => stripMarkdown(text)
|
||||||
|
|
||||||
return { topics, selectedTopic, articles, sanitizeDescription, isLoadingPosts, handleScroll, selectedCategory, selectedTags, tagOptions, categoryOptions, isMobile, homePage }
|
return { topics, selectedTopic, articles, sanitizeDescription, isLoadingPosts, selectedCategory, selectedTags, tagOptions, categoryOptions, isMobile }
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
</script>
|
</script>
|
||||||
@@ -397,11 +382,9 @@ export default {
|
|||||||
<style scoped>
|
<style scoped>
|
||||||
.home-page {
|
.home-page {
|
||||||
background-color: var(--background-color);
|
background-color: var(--background-color);
|
||||||
height: 100%;
|
|
||||||
display: flex;
|
display: flex;
|
||||||
flex-direction: column;
|
flex-direction: column;
|
||||||
align-items: center;
|
align-items: center;
|
||||||
overflow-y: auto;
|
|
||||||
container-type: inline-size;
|
container-type: inline-size;
|
||||||
container-name: home-page;
|
container-name: home-page;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -628,8 +628,6 @@ export default {
|
|||||||
|
|
||||||
.message-page {
|
.message-page {
|
||||||
background-color: var(--background-color);
|
background-color: var(--background-color);
|
||||||
height: 100%;
|
|
||||||
overflow-y: auto;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
.message-page-header {
|
.message-page-header {
|
||||||
|
|||||||
Reference in New Issue
Block a user