Skip to content

Commit 880a2a3

Browse files
committed
fix: optimize code
1 parent df271f2 commit 880a2a3

File tree

3 files changed

+112
-41
lines changed

3 files changed

+112
-41
lines changed

packages/vuepress-theme-reco/src/client/components/Home/Blog.vue

Lines changed: 25 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -27,7 +27,7 @@
2727
<ul class="category-wrapper">
2828
<li
2929
class="category-item"
30-
v-for="({ label, length, categoryValue }, key, index) in categories"
30+
v-for="({ label, length, categoryValue }, index) in categories"
3131
:key="index">
3232
<router-link
3333
class="category-link"
@@ -46,7 +46,7 @@
4646
<ul class="tag-wrapper">
4747
<li
4848
class="tag-item"
49-
v-for="({ label, categoryValue }, key, index) in tags"
49+
v-for="({ label, categoryValue }, index) in tags"
5050
:key="index"
5151
:style="{ borderColor: createOneColor() }"
5252
>
@@ -61,7 +61,7 @@
6161
</template>
6262

6363
<script setup lang="ts">
64-
import { computed, onMounted, ref, watch } from "vue";
64+
import { computed, onMounted, onUnmounted, ref, watch } from "vue";
6565
import { useRouteLocale, useRoute, useRouter, withBase } from 'vuepress/client'
6666
import { useExtendPageData } from '@vuepress-reco/vuepress-plugin-page/composables'
6767
@@ -139,22 +139,27 @@ if (!__VUEPRESS_SSR__) {
139139
})
140140
})
141141
142-
window.addEventListener(
143-
'scroll',
144-
throttle(() => {
145-
const card = document.querySelector('.info-wrapper')
146-
147-
if (card) {
148-
// @ts-ignore
149-
card.setAttribute('data-x', card.offsetLeft)
150-
// @ts-ignore
151-
card.setAttribute('data-y', card.offsetTop)
152-
// @ts-ignore
153-
card.setAttribute('data-width', card.clientWidth)
154-
// @ts-ignore
155-
card.setAttribute('data-height', card.clientHeight)
156-
}
157-
}, 50)
158-
)
142+
// 使用远高的节流时间减少性能影响
143+
const scrollHandler = throttle(() => {
144+
const card = document.querySelector('.info-wrapper')
145+
146+
if (card) {
147+
// @ts-ignore
148+
card.setAttribute('data-x', card.offsetLeft)
149+
// @ts-ignore
150+
card.setAttribute('data-y', card.offsetTop)
151+
// @ts-ignore
152+
card.setAttribute('data-width', card.clientWidth)
153+
// @ts-ignore
154+
card.setAttribute('data-height', card.clientHeight)
155+
}
156+
}, 200) // 增加到200ms减少执行频率
157+
158+
window.addEventListener('scroll', scrollHandler)
159+
160+
// 在组件卸载时清理事件监听器
161+
onUnmounted(() => {
162+
window.removeEventListener('scroll', scrollHandler)
163+
})
159164
}
160165
</script>

packages/vuepress-theme-reco/src/client/components/PostList/PostItem.vue

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
<template>
2-
<MagicCard class="post-item-container">
2+
<!-- 使用v-memo来避免不必要的重新渲染 -->
3+
<MagicCard class="post-item-container" v-memo="[data.path, data.title, data.frontmatter?.sticky, solution]">
34
<div class="title">
45
<SafeRouterLink :to="data.path">
56
<Xicons v-if="data.frontmatter?.sticky" :icon="IconStar" />

packages/vuepress-theme-reco/src/client/components/SafeRouterLink.vue

Lines changed: 85 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -11,11 +11,22 @@
1111
// 注意:我们有意使用普通JavaScript而非Typescript
1212
// 这可以避免TS在编译期间检查导入的组件
1313
14-
import { h, shallowRef, computed } from 'vue'
14+
import { shallowRef, computed, onMounted, onBeforeMount } from 'vue'
15+
import { useRouter } from 'vuepress/client'
1516
1617
// 安全地检测我们是否在服务器上
1718
const isServer = typeof window === 'undefined'
1819
20+
// 获取路由实例
21+
let router = null
22+
if (!isServer) {
23+
try {
24+
router = useRouter()
25+
} catch (e) {
26+
console.warn('SafeRouterLink: Error getting router instance', e)
27+
}
28+
}
29+
1930
// 使用 shallowRef 避免 Vue 深入解析导入的组件
2031
const linkComponent = shallowRef('a')
2132
@@ -41,15 +52,51 @@ const props = defineProps({
4152
4253
// 计算出给组件的属性
4354
const componentProps = computed(() => {
55+
// 处理对象形式的 to 属性,确保在使用 a 标签时有正确的 href
56+
const toPath = typeof props.to === 'string'
57+
? props.to
58+
: (props.to && typeof props.to === 'object' && props.to.path)
59+
? props.to.path
60+
: '/'
61+
4462
if (isServer) {
45-
// 在服务器端,我们使用普通的a标签
63+
// 在服务器端使用正常的a标签
4664
return {
4765
class: 'router-link-fallback',
48-
href: typeof props.to === 'string' ? props.to : '',
66+
href: toPath,
67+
// 添加 onclick 防止默认行为
68+
onclick: 'return false;',
69+
...props.$attrs
70+
}
71+
} else if (linkComponent.value === 'a') {
72+
// 在客户端但RouterLink还未加载完成时
73+
// 使用 a 标签并自己处理导航逻辑
74+
return {
75+
class: 'router-link-fallback',
76+
href: toPath,
77+
// 实现对点击事件的处理,阻止页面刷新但仍然能实现路由跳转
78+
onClick: (e) => {
79+
e.preventDefault(); // 阻止默认行为
80+
81+
// 如果有路由实例,手动调用导航
82+
if (router) {
83+
const path = typeof props.to === 'string' ? props.to :
84+
(props.to && typeof props.to === 'object') ? props.to : '/';
85+
86+
if (props.replace) {
87+
router.replace(path);
88+
} else {
89+
router.push(path);
90+
}
91+
} else {
92+
// 如果没有路由实例,回退到正常行为
93+
window.location.href = toPath;
94+
}
95+
},
4996
...props.$attrs
5097
}
5198
} else {
52-
// 在客户端,我们使用RouterLink的属性
99+
// 在客户端且RouterLink已加载,使用RouterLink的属性
53100
return {
54101
to: props.to,
55102
custom: props.custom,
@@ -60,24 +107,42 @@ const componentProps = computed(() => {
60107
}
61108
})
62109
63-
// 只在客户端环境下动态导入和使用RouterLink
64-
if (!isServer) {
65-
// 时间函数延迟运行,确保到了客户端才运行
66-
setTimeout(() => {
67-
try {
68-
// 动态导入RouterLink
69-
// 先尝试从 vuepress/client 中导入,这样在不同包管理器下都能正常工作
70-
import('vuepress/client').then(vuepress => {
71-
// 检查是否存在RouterLink
110+
// 在组件创建前就开始加载 RouterLink
111+
onBeforeMount(() => {
112+
if (!isServer) {
113+
// 使用缓存避免重复导入RouterLink
114+
if (window.__ROUTER_LINK_LOADED__) {
115+
linkComponent.value = window.__ROUTER_LINK_COMPONENT__
116+
return
117+
}
118+
119+
// 使用立即执行的异步函数
120+
(async () => {
121+
try {
122+
// 使用 await 等待导入完成
123+
const vuepress = await import('vuepress/client')
72124
if (vuepress.RouterLink) {
125+
// 缓存RouterLink组件引用
126+
window.__ROUTER_LINK_COMPONENT__ = vuepress.RouterLink
127+
window.__ROUTER_LINK_LOADED__ = true
73128
linkComponent.value = vuepress.RouterLink
74129
}
75-
}).catch(e => {
130+
} catch (e) {
76131
console.warn('SafeRouterLink: Failed to load RouterLink, using fallback link', e)
77-
})
78-
} catch (e) {
79-
console.warn('SafeRouterLink: Error importing RouterLink', e)
80-
}
81-
}, 0)
82-
}
132+
}
133+
})();
134+
}
135+
})
136+
137+
// 也保留 onMounted 钩子,确保 RouterLink 被正确加载
138+
onMounted(() => {
139+
if (!isServer && !window.__ROUTER_LINK_LOADED__) {
140+
// 如果 onBeforeMount 没有成功加载,再次尝试
141+
setTimeout(() => {
142+
if (window.__ROUTER_LINK_LOADED__) {
143+
linkComponent.value = window.__ROUTER_LINK_COMPONENT__
144+
}
145+
}, 0)
146+
}
147+
})
83148
</script>

0 commit comments

Comments
 (0)