1
1
import { siteConfig } from '@/lib/config'
2
2
import Head from 'next/head'
3
3
import { useEffect , useRef , useState } from 'react'
4
+
4
5
/**
5
6
* 图片懒加载
6
7
* @param {* } param0
@@ -21,20 +22,21 @@ export default function LazyImage({
21
22
} ) {
22
23
const maxWidth = siteConfig ( 'IMAGE_COMPRESS_WIDTH' )
23
24
const defaultPlaceholderSrc = siteConfig ( 'IMG_LAZY_LOAD_PLACEHOLDER' )
24
-
25
25
const imageRef = useRef ( null )
26
- const [ adjustedSrc , setAdjustedSrc ] = useState (
27
- placeholderSrc || siteConfig ( 'IMG_LAZY_LOAD_PLACEHOLDER' )
26
+ const [ currentSrc , setCurrentSrc ] = useState (
27
+ placeholderSrc || defaultPlaceholderSrc
28
28
)
29
29
30
- if ( ! placeholderSrc ) {
31
- placeholderSrc = siteConfig ( 'IMG_LAZY_LOAD_PLACEHOLDER' )
32
- }
33
-
34
30
/**
35
- * 图片加载成功回调
31
+ * 占位图加载成功
36
32
*/
37
- const handleImageLoad = ( ) => {
33
+ const handleThumbnailLoaded = ( ) => {
34
+ if ( typeof onLoad === 'function' ) {
35
+ // onLoad() // 触发传递的onLoad回调函数
36
+ }
37
+ }
38
+ // 原图加载完成
39
+ const handleImageLoaded = img => {
38
40
if ( typeof onLoad === 'function' ) {
39
41
onLoad ( ) // 触发传递的onLoad回调函数
40
42
}
@@ -44,13 +46,27 @@ export default function LazyImage({
44
46
*/
45
47
const handleImageError = ( ) => {
46
48
if ( imageRef . current ) {
47
- imageRef . current . src = defaultPlaceholderSrc
49
+ // 尝试加载 placeholderSrc,如果失败则加载 defaultPlaceholderSrc
50
+ if ( imageRef . current . src !== placeholderSrc && placeholderSrc ) {
51
+ imageRef . current . src = placeholderSrc
52
+ } else {
53
+ imageRef . current . src = defaultPlaceholderSrc
54
+ }
48
55
}
49
56
}
50
57
51
58
useEffect ( ( ) => {
52
- const adjustedImageSrc = adjustImgSize ( src , maxWidth )
53
- setAdjustedSrc ( adjustedImageSrc )
59
+ const adjustedImageSrc =
60
+ adjustImgSize ( src , maxWidth ) || defaultPlaceholderSrc
61
+
62
+ // 加载原图
63
+ const img = new Image ( )
64
+ img . src = adjustedImageSrc
65
+ img . onload = ( ) => {
66
+ setCurrentSrc ( adjustedImageSrc )
67
+ handleImageLoaded ( adjustedImageSrc )
68
+ }
69
+ img . onerror = handleImageError
54
70
55
71
const observer = new IntersectionObserver (
56
72
entries => {
@@ -79,9 +95,9 @@ export default function LazyImage({
79
95
// 动态添加width、height和className属性,仅在它们为有效值时添加
80
96
const imgProps = {
81
97
ref : imageRef ,
82
- src : priority ? adjustedSrc : placeholderSrc ,
98
+ src : currentSrc ,
83
99
alt : alt ,
84
- onLoad : handleImageLoad ,
100
+ onLoad : handleThumbnailLoaded , // 缩略图加载完成
85
101
onError : handleImageError // 添加onError处理函数
86
102
}
87
103
@@ -106,31 +122,33 @@ export default function LazyImage({
106
122
if ( style ) {
107
123
imgProps . style = style
108
124
}
125
+
109
126
return (
110
127
< >
111
128
{ /* eslint-disable-next-line @next/next/no-img-element */ }
112
129
< img { ...imgProps } />
113
130
{ /* 预加载 */ }
114
131
{ priority && (
115
132
< Head >
116
- < link rel = 'preload' as = 'image' href = { adjustedSrc } />
133
+ < link rel = 'preload' as = 'image' href = { adjustImgSize ( src , maxWidth ) } />
117
134
</ Head >
118
135
) }
119
136
</ >
120
137
)
121
138
}
139
+
122
140
/**
123
141
* 根据窗口尺寸决定压缩图片宽度
124
142
* @param {* } src
125
143
* @param {* } maxWidth
126
144
* @returns
127
145
*/
128
-
129
146
const adjustImgSize = ( src , maxWidth ) => {
130
147
if ( ! src ) {
131
- return siteConfig ( 'IMG_LAZY_LOAD_PLACEHOLDER' )
148
+ return null
132
149
}
133
- const screenWidth = window . screen . width
150
+ const screenWidth =
151
+ ( typeof window !== 'undefined' && window ?. screen ?. width ) || maxWidth
134
152
135
153
// 屏幕尺寸大于默认图片尺寸,没必要再压缩
136
154
if ( screenWidth > maxWidth ) {
0 commit comments