react-lazyimg-component v1.0.0 是使用 Typescript、React Hooks、Intersection Observer API完全重构的,React 图片懒加载小组件。并且组件参考了React Transition Group 的 SwitchTransition 动画实现原理 ,引入全新的渐进性自然过渡效果(如下图 方案 B 所示)。
Demo 效果
singsong: Demo 中第一张图片未使用 渐进性自然过渡效果,会存在跳闪现象。第二张图片使用 渐进性自然过渡效果。效果更加自然!😀
- Typescript 静态类型检查,代码提示与补全更加完善
- React Hooks 实现
- Intersection Observer API 取代 scroll 事件,代码更加简洁,性能更好。并且做了兼容处理。
- 兼容服务端渲染 SSR
- 定制组件的默认
props
- 支持 React 组件式 placeholder
- 支持动画效果作用于父级元素
- 支持响应式图片( picture / srcset )
- 默认开启全新的渐进性自然过渡效果
// npm
$> npm install react-lazyimg-component
// yarn
$> yarn add react-lazyimg-component
// 引入 react-lazyimg-component
import Lazyimg from 'react-lazyimg-component';
// 调用
<Lazyimg className="lazy" src={'http://zhansingsong.github.io/lazyimg/22.4582fc71.jpg'} />;
// 引入 react-lazyimg-component
import Lazyimg, {LazyimgWrapper} from 'react-lazyimg-component';
<LazyimgWrapper>
<Lazyimg className="lazy" src={'http://zhansingsong.github.io/lazyimg/bg9.b4fca14f.jpg'} />
</LazyimgWrapper>;
// 定义 placeholder 组件
import React from 'react';
import './style.scss';
export default (props) => {
let {className, text, img, children} = props;
return (
<div
className={['placeholder', className]
.filter((item) => {
if (item) {
return item;
}
})
.join(' ')}
>
{img && <img src={img} className="placeholder-img" />}
{text && <span className="placeholder-text">{children || text}</span>}
</div>
);
};
// 引入 react-lazyimg-component
import Lazyimg from 'react-lazyimg-component';
// 引入 Placeholder
import Placeholder from './Placeholder';
// 引入 fire.svg
import Fire from './img/fire.svg';
<Lazyimg
placeholder={<Placeholder img={Fire} />}
animateType="animation"
animateClassName={['animated', 'rollIn']}
className="lazy"
timeout={1000}
src={'http://zhansingsong.github.io/lazyimg/bg9.b4fca14f.jpg'}
/>;
// 引入 react-lazyimg-component
import Lazyimg, {LazyimgWrapper, withLazyimg} from 'react-lazyimg-component';
// 引入 Placeholder
import Placeholder from './Placeholder';
// 引入 loading.svg
import Loading from './img/loading.svg';
// 使用 withLazyimg 配置
const Lazy = withLazyimg({
placeholder: <Placeholder img={Loading} />,
threshold: 0.98,
});
<LazyimgWrapper style={{height: '100%', width: '100%'}}>
<Lazy className="lazy" src={'http://zhansingsong.github.io/lazyimg/bg9.b4fca14f.jpg'} />
</LazyimgWrapper>;
-
动画样式
.transition-enter { opacity: 0; transform: scale(1.04); } .transition-enter-active { opacity: 1; transform: scale(1); transition: opacity 400ms, transform 400ms; }
-
组件
// 引入 react-lazyimg-component import Lazyimg from 'react-lazyimg-component'; <Lazyimg animateType="transition" animateClassName={['transition-enter', 'transition-enter-active']} className="lazy" timeout={400} src={'http://zhansingsong.github.io/lazyimg/bg9.b4fca14f.jpg'} />;
singsong: 这里
"transition"
使用的是 进动画(不可见 ---> 可见)。如果使用"LazyimgWrapper"
,就需要使用 出动画(可见 ---> 不可见)。同时不要忘记指定timeout={1000}
😬
使用 animate.css
样式动画库实现过渡效果。
// 引入 react-lazyimg-component
import Lazyimg, {LazyimgWrapper, withLazyimg} from 'react-lazyimg-component';
// 引入 Placeholder
import Placeholder from '../Placeholder';
// 引入 loading.svg
import Loading from '../../img/loading.svg';
// 使用 withLazyimg 配置
const Lazy = withLazyimg({
placeholder: <Placeholder img={Loading} />,
threshold: 0.98,
});
<LazyimgWrapper style={{height: '100%', width: '100%'}}>
<Lazy
animateType="animation"
animateClassName={['animated', 'slideOutDown']}
timeout={1000}
className="lazy"
src={'http://zhansingsong.github.io/lazyimg/bg9.b4fca14f.jpg'}
/>
</LazyimgWrapper>;
singsong:这里
"animation"
依赖于animate.css
, 并且使用了"LazyimgWrapper"
,就需要使用 出动画(可见 ---> 不可见),如 "slideOutDown"。同时需要指定timeout={1000}
// 引入 react-lazyimg-component
import Lazyimg from 'react-lazyimg-component';
// 调用
<Lazyimg
className="lazy"
src={'http://zhansingsong.github.io/lazyimg/22.4582fc71.jpg'}
loaded={(el) => {
// 自定义动画效果
window.Velocity(el, 'transition.whirlIn', {
// 需要引入 Velocity 动画库
duration: 600,
});
// 避免执行默认动画逻辑
return true;
}}
/>;
// 指定动画效果作用于该父级元素
<div className="example-wp">
<Title title="父级动画效果" className="sub" />
<div className="example-img">
<Lazyimg
className="lazy"
src={'http://zhansingsong.github.io/lazyimg/22.4582fc71.jpg'}
animateType="animation"
animateClassName={['animated', 'flipInY']}
timeout={1000}
parent=".example-wp" // 指定父级元素选择器,也可以指定父级层级level:2
/>
</div>
</div>
singsong:当图片元素加载完,动画效果会作用在指定的父级元素上。
// dpr
<Lazyimg
className="lazy"
src={'http://zhansingsong.github.io/lazyimg/22.4582fc71.jpg'}
srcSet="source_1x.png 1x, source_2x.png 2x, source_3x.png 3x, source_3.5x.png 3.5x"
timeout={1000}
animateType="animation"
animateClassName={['animated', 'bounceIn']}
/>
// media-query、srcSet、sizes
<Lazyimg
className="lazy"
src={'http://zhansingsong.github.io/lazyimg/22.4582fc71.jpg'}
srcSet="source_360.png 360w, source_640.png 640w, source_980.png 980w, source_1290.png 1290w"
sizes="(min-width: 370px) 100vw, (min-width: 640px) 75vw,(max-width: 980px) 50vw, 360"
timeout={1000}
animateType="animation"
animateClassName={['animated', 'bounceIn']}
/>
// picture
<picture>
<source media="(min-width: 650px)" srcSet="https://www.w3schools.com/tags/img_pink_flowers.jpg" />
<source media="(min-width: 465px)" srcSet="https://www.w3schools.com/tags/img_white_flower.jpg"/>
<Lazyimg
className="lazy"
src={'http://zhansingsong.github.io/lazyimg/22.4582fc71.jpg'}
timeout={1000}
animateType="animation"
animateClassName={['animated', 'zoomIn']}
/>
</picture>
通过 props
来决定懒加载的行为,to use is super easy😎。
-
Lazyimg:默认组件
// 图片地址 src: string; // 响应式【可选】 srcSet: string; // 指定元素的 node Type,默认为 `img`【可选】 element?: string; // 为 `true` 时,直接替换 src,不使用懒加载行为。默认为 'false'【可选】 force?: boolean; // 在图片加载好替换前 hook 回调 【可选】 loaded?: (el?: HTMLElement) => void; // 动画执行完完 hook 回调【可选】 end?: (el?: HTMLElement) => void; // 过渡动画类型【可选】 animateType?: 'none' | 'transition' | 'animation'; // 动画作用类名【可选】 animateClassName?: string[]; // 动画执行时长,用于动画事件的不兼容时回退处理【可选】 timeout?: number; // 动画作用于父级元素【可选】 parent?: number | string; // 指定图片加载前,显示内容【可选】 placeholder?: React.ReactNode; // Intersection observer options:https://developer.mozilla.org/zh-CN/docs/Web/API/Intersection_Observer_API 【可选】 root?: Element; rootMargin?: string; threshold?: number[];
-
src:图片地址
-
srcSet:响应式图片地址
-
force:为
true
时,直接替换 src,不使用懒加载行为。默认为false
。 -
loaded:在图片加载好替换前 hook 回调。回调参数为当前元素
el
。 -
end:动画执行完完 hook 回调。回调参数为当前元素
el
。 -
animateType:动画类型。可取值:
'animation'
:使用animation
动画'transition'
:使用transition
动画'none'
:不使用动画
-
animateClassName:动画作用类名
- 使用
'animation'
时,推荐使用animate.css
。取值方式为:['animate__animated', 'animate__bounce']
或['animated', 'bounce']
。singsong: 如果自己实现,请遵照
animate.css
实现使用方式来。 - 使用
'transition'
时,请按照如下的实现方式:取值方式为:.fade-enter { opacity: 0; } .fade-enter-active { opacity: 1; transition: opacity 500ms; }
['fade-enter', 'fade-enter-active']
- 使用
-
timeout:动画执行时长,用于动画事件的不兼容时回退处理。如
transition: opacity 500ms;
,timeout 就为500
。 -
parent:用于指定动画效果作用于元素的哪个父级元素。可取值:
- 父元素的 selector 选择器(字符串)
- 父级层级 level(整数)
-
element:指定 react 将生成的元素类型,默认为'img'。
-
placeholder:占位元素,除了支持普通的图片外,还支持 react 组件。
-
-
withLazyimg:定制
Lazyimg
组件的默认props
。如使用withLazying
配置 react 组件式 placeholder// 引入 react-lazyimg-component import Lazyimg, {LazyimgWrapper, withLazyimg} from 'react-lazyimg-component'; // 引入 Placeholder import Placeholder from './Placeholder'; // 引入 loading.svg import Loading from './img/loading.svg'; // 使用 withLazyimg 配置 const Lazy = withLazyimg({ placeholder: <Placeholder img={Loading} />, threshold: 0.98, }); <LazyimgWrapper style={{height: '100%', width: '100%'}}> <Lazy className="lazy" src={'http://zhansingsong.github.io/lazyimg/bg9.b4fca14f.jpg'} /> </LazyimgWrapper>;
-
LazyimgWrapper:包裹组件,用于包裹
Lazyimg
组件,方便构建渐进性自然过渡效果。