This commit is contained in:
李琦
2026-01-15 14:24:30 +08:00
parent f81be649aa
commit 18d3e993f9
9 changed files with 72 additions and 57 deletions

View File

@@ -1,9 +1,17 @@
import { onMounted, onUnmounted } from 'vue'
import { onMounted, onUnmounted, nextTick } from 'vue'
export function useScrollAnimation() {
let observer: IntersectionObserver | null = null
const observe = () => {
const initObserver = async () => {
// Wait for DOM updates
await nextTick()
// Disconnect existing observer if any
if (observer) {
observer.disconnect()
}
observer = new IntersectionObserver((entries) => {
entries.forEach(entry => {
if (entry.isIntersecting) {
@@ -17,19 +25,28 @@ export function useScrollAnimation() {
rootMargin: '50px' // Pre-load slightly before element comes into view
})
document.querySelectorAll('.animate-slide-down, .animate-reveal').forEach(el => {
observer?.observe(el)
})
const elements = document.querySelectorAll('.animate-slide-down, .animate-reveal')
if (elements.length === 0) {
// Retry once if no elements found (e.g. data loaded but DOM not quite ready)
setTimeout(() => {
document.querySelectorAll('.animate-slide-down, .animate-reveal').forEach(el => {
observer?.observe(el)
})
}, 100)
} else {
elements.forEach(el => {
observer?.observe(el)
})
}
}
onMounted(() => {
// Small delay to ensure DOM is ready
setTimeout(observe, 100)
})
onUnmounted(() => {
if (observer) {
observer.disconnect()
}
})
return {
initObserver
}
}

View File

@@ -111,6 +111,8 @@ const profile = ref<Profile>({
const loading = ref(false)
const error = ref('')
const { initObserver } = useScrollAnimation()
// 模拟API调用实际项目中应替换为真实API
const fetchProfileData = async () => {
loading.value = true
@@ -134,6 +136,8 @@ const fetchProfileData = async () => {
},
techStack: ['Vue 3', 'React', 'TypeScript', 'Three.js', 'Golang', 'Tailwind CSS', 'Vite', 'Gin']
}
// 初始化动画
initObserver()
} catch (err) {
console.error('Error fetching profile data:', err)
error.value = '获取个人资料失败,请稍后重试'
@@ -143,14 +147,8 @@ const fetchProfileData = async () => {
}
}
onBeforeMount(() => {
fetchProfileData()
})
onMounted(() => {
// 启用滚动动画
useScrollAnimation()
fetchProfileData()
// 初始化Lucide图标
if (window.lucide) {
window.lucide.createIcons()

View File

@@ -52,12 +52,16 @@ const blogPosts = ref<Post[]>([])
const loading = ref(false)
const error = ref('')
const { initObserver } = useScrollAnimation()
const fetchBlogPosts = async () => {
loading.value = true
error.value = ''
try {
const posts = await fetchPosts()
blogPosts.value = posts
// 初始化动画 - 在数据加载完成后
initObserver()
} catch (err) {
console.error('Error fetching blog posts:', err)
error.value = '获取博客文章失败,请稍后重试'
@@ -66,14 +70,8 @@ const fetchBlogPosts = async () => {
}
}
onBeforeMount(() => {
fetchBlogPosts()
})
onMounted(() => {
// 启用滚动动画
useScrollAnimation()
fetchBlogPosts()
// 初始化Lucide图标
if (window.lucide) {
window.lucide.createIcons()

View File

@@ -81,6 +81,8 @@ const post = ref<Post>({
const loading = ref(false)
const error = ref('')
const { initObserver } = useScrollAnimation()
const fetchBlogDetail = async () => {
loading.value = true
error.value = ''
@@ -88,6 +90,8 @@ const fetchBlogDetail = async () => {
const postData = await fetchPost(postId)
if (postData) {
post.value = postData
// 初始化动画 - 在数据加载完成后
initObserver()
} else {
error.value = '未找到该文章'
}
@@ -99,14 +103,8 @@ const fetchBlogDetail = async () => {
}
}
onBeforeMount(() => {
fetchBlogDetail()
})
onMounted(() => {
// 启用滚动动画
useScrollAnimation()
fetchBlogDetail()
// 初始化Lucide图标
if (window.lucide) {
window.lucide.createIcons()

View File

@@ -108,6 +108,8 @@ import { ref, onMounted, onBeforeMount } from 'vue'
import { fetchWorks, fetchPosts, Work, Post } from '../services/api'
import { useScrollAnimation } from '../composables/useScrollAnimation'
const { initObserver } = useScrollAnimation()
const latestWork = ref<Work>({
id: 'nova',
title: 'Nova 交易平台',
@@ -137,15 +139,16 @@ const fetchHomeData = async () => {
loading.value = true
error.value = ''
try {
// 获取最新作品
const works = await fetchWorks()
if (works.length > 0) {
const [works, posts] = await Promise.all([
fetchWorks(),
fetchPosts()
])
if (works && works.length > 0) {
latestWork.value = works[0]
}
// 获取精选文章
const posts = await fetchPosts()
if (posts.length > 0) {
if (posts && posts.length > 0) {
featuredPost.value = posts[0]
}
} catch (err) {
@@ -153,15 +156,12 @@ const fetchHomeData = async () => {
error.value = '获取首页数据失败'
} finally {
loading.value = false
// 启用滚动动画
initObserver()
}
}
onBeforeMount(() => {
onMounted(() => {
fetchHomeData()
})
onMounted(() => {
// 启用滚动动画
useScrollAnimation()
})
</script>

View File

@@ -246,9 +246,11 @@ onBeforeMount(() => {
fetchServicesData()
})
const { initObserver } = useScrollAnimation()
onMounted(() => {
// 启用滚动动画
useScrollAnimation()
initObserver()
// 初始化Lucide图标
if (window.lucide) {

View File

@@ -52,12 +52,16 @@ const snippets = ref<Snippet[]>([])
const loading = ref(false)
const error = ref('')
const { initObserver } = useScrollAnimation()
const fetchSnippetsData = async () => {
loading.value = true
error.value = ''
try {
const snippetsData = await fetchSnippets()
snippets.value = snippetsData
// 初始化动画 - 在数据加载完成后
initObserver()
} catch (err) {
console.error('Error fetching snippets:', err)
error.value = '获取代码片段失败,请稍后重试'
@@ -111,6 +115,8 @@ export const useMousePosition = () => {
type: 'animate'
}
]
// 静态数据加载后也要初始化动画
initObserver()
} finally {
loading.value = false
}
@@ -136,14 +142,8 @@ const openSnippet = (snippet: any) => {
}
}
onBeforeMount(() => {
fetchSnippetsData()
})
onMounted(() => {
// 启用滚动动画
useScrollAnimation()
fetchSnippetsData()
// 初始化Lucide图标
if (window.lucide) {
window.lucide.createIcons()

View File

@@ -124,6 +124,8 @@ const work = ref<Work>({
const loading = ref(true)
const error = ref('')
const { initObserver } = useScrollAnimation()
const updateScrollProgress = () => {
const scrollTop = window.scrollY
const docHeight = document.documentElement.scrollHeight
@@ -142,6 +144,8 @@ const fetchWorkDetails = async () => {
const workData = await fetchWork(workId)
if (workData) {
work.value = workData
// 初始化动画 - 在数据加载完成后
initObserver()
} else {
error.value = '未找到该作品'
}
@@ -154,9 +158,6 @@ const fetchWorkDetails = async () => {
}
onMounted(() => {
// 启用滚动动画
useScrollAnimation()
fetchWorkDetails()
// 初始化Lucide图标
if (window.lucide) {

View File

@@ -90,11 +90,15 @@ const works = ref<Work[]>([])
const loading = ref(false)
const error = ref('')
const { initObserver } = useScrollAnimation()
const fetchWorksData = async () => {
loading.value = true
error.value = ''
try {
works.value = await fetchWorks()
// 初始化动画 - 在数据加载完成后
initObserver()
} catch (err) {
error.value = '获取作品失败,请稍后重试'
console.error('Error fetching works:', err)
@@ -104,9 +108,6 @@ const fetchWorksData = async () => {
}
onMounted(() => {
// 启用滚动动画
useScrollAnimation()
fetchWorksData()
// 初始化Lucide图标
if (window.lucide) {