图片懒加载组件,优化性能,优化SEO

This commit is contained in:
tangly1024.com
2023-07-21 11:46:31 +08:00
parent 0637af15ad
commit 0aecf06729
40 changed files with 179 additions and 104 deletions

88
components/LazyImage.js Normal file
View File

@@ -0,0 +1,88 @@
import React, { useEffect, useRef, useState } from 'react'
/**
* 默认懒加载占位图
*/
const loadingSVG = (
<svg
width="100"
height="100"
viewBox="0 0 100 100"
xmlns="http://www.w3.org/2000/svg"
fill="#ccc"
>
<circle cx="50" cy="50" r="42" strokeWidth="8" />
</svg>
)
/**
* 图片懒加载
* @param {*} param0
* @returns
*/
export default function LazyImage({ id, src, alt, placeholderSrc = loadingSVG, className, width, height, onLoad, style }) {
const imageRef = useRef(null)
const [imageLoaded, setImageLoaded] = useState(false)
const handleImageLoad = () => {
setImageLoaded(true)
if (typeof onLoad === 'function') {
onLoad() // 触发传递的onLoad回调函数
}
}
useEffect(() => {
const observer = new IntersectionObserver(
(entries) => {
entries.forEach((entry) => {
if (entry.isIntersecting) {
const lazyImage = entry.target
lazyImage.src = src
observer.unobserve(lazyImage)
}
})
},
{ rootMargin: '50px 0px' } // Adjust the rootMargin as needed to trigger the loading earlier or later
)
if (imageRef.current) {
observer.observe(imageRef.current)
}
return () => {
if (imageRef.current) {
observer.unobserve(imageRef.current)
}
}
}, [src])
// 动态添加width、height和className属性仅在它们为有效值时添加
const imgProps = {
ref: imageRef,
src: imageLoaded ? src : placeholderSrc,
alt: alt,
onLoad: handleImageLoad
}
if (id) {
imgProps.id = id
}
if (width && width !== 'auto') {
imgProps.width = width
}
if (height && height !== 'auto') {
imgProps.height = height
}
if (className) {
imgProps.className = className
}
if (style) {
imgProps.style = style
}
return (
// eslint-disable-next-line @next/next/no-img-element
<img {...imgProps} />
)
}

View File

@@ -1,3 +1,5 @@
import LazyImage from './LazyImage'
/**
* notion的图标icon
* 可能是emoji 可能是 svg 也可能是 图片
@@ -9,9 +11,7 @@ const NotionIcon = ({ icon }) => {
}
if (icon.startsWith('http') || icon.startsWith('data:')) {
// return <Image src={icon} width={30} height={30}/>
// eslint-disable-next-line @next/next/no-img-element
return <img src={icon} className='w-8 h-8 my-auto inline mr-1'/>
return <LazyImage src={icon} className='w-8 h-8 my-auto inline mr-1'/>
}
return <span className='mr-1'>{icon}</span>