PkgLogo favicon 懒加载:IntersectionObserver 进入视口才发请求,大列表不再一次性并发数百个图标
This commit is contained in:
@@ -1,6 +1,7 @@
|
||||
<script setup>
|
||||
// 包 logo:优先取主页域名的 favicon(浏览器端加载,离线/加载失败回退首字母徽标)
|
||||
import { computed, ref, watch } from 'vue'
|
||||
// 懒加载:仅当组件进入视口(提前 120px)才发起图标请求,大列表不一次性并发数百个请求
|
||||
import { computed, ref, watch, onMounted, onBeforeUnmount } from 'vue'
|
||||
|
||||
const props = defineProps({
|
||||
name: { type: String, default: '' },
|
||||
@@ -8,6 +9,30 @@ const props = defineProps({
|
||||
homepage: { type: String, default: '' },
|
||||
})
|
||||
|
||||
// —— 视口懒加载状态 ——
|
||||
const inView = ref(false)
|
||||
const rootEl = ref(null)
|
||||
let io = null
|
||||
onMounted(() => {
|
||||
if (typeof IntersectionObserver === 'undefined' || !rootEl.value) {
|
||||
inView.value = true // 不支持 IO 时退化为立即加载
|
||||
return
|
||||
}
|
||||
io = new IntersectionObserver(
|
||||
(entries) => {
|
||||
if (entries[0] && entries[0].isIntersecting) {
|
||||
inView.value = true
|
||||
if (io) io.disconnect()
|
||||
}
|
||||
},
|
||||
{ rootMargin: '120px 0px' },
|
||||
)
|
||||
io.observe(rootEl.value)
|
||||
})
|
||||
onBeforeUnmount(() => {
|
||||
if (io) io.disconnect()
|
||||
})
|
||||
|
||||
const letter = computed(() => {
|
||||
const base = (props.name.split('/').pop() || props.name || '?').trim()
|
||||
return (base[0] || '?').toUpperCase()
|
||||
@@ -52,9 +77,9 @@ function onImgErr() { imgOk.value = false }
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<span class="pkg-logo" :style="style" :title="name">
|
||||
<!-- img 始终挂载以触发 load/error;加载成功后显示,失败回退字母徽标 -->
|
||||
<img v-if="faviconUrl" class="fav" :class="{ on: imgOk }" :src="faviconUrl" alt="" @load="onImgOk" @error="onImgErr" />
|
||||
<span ref="rootEl" class="pkg-logo" :style="style" :title="name">
|
||||
<!-- 进入视口后才挂载 img 发起 favicon 请求;加载成功后显示,失败回退字母徽标 -->
|
||||
<img v-if="faviconUrl && inView" class="fav" :class="{ on: imgOk }" :src="faviconUrl" alt="" @load="onImgOk" @error="onImgErr" />
|
||||
<span v-show="!imgOk" class="lt">{{ letter }}</span>
|
||||
</span>
|
||||
</template>
|
||||
|
||||
Reference in New Issue
Block a user