这是我参与「第四届青训营 」笔记创作活动的第二天
基于react&hooks的轮播图制作
在月影大佬教我们写js的时候提到了组件制作,并以轮播图为例进行讲解,而作者最近刚好在临摹网易云音乐 的页面,而其中偌大的一个组件就是轮播图,
尽管作者之前已有实现,但实现的并不优雅:毕竟组件需要一定的解耦,而之前作者是采用了redux做状态管理,与页面是一个强耦合的关系。于是在学习了那节课之后,笔者重新制作轮播图组件
不过与月影大大教的不一样的是我并没有采用原生的js,而是使用了react与hooks制作轮播图
以下就是制作思路:
-
HTML与CSS构思结构与样式:其实这一部分可以直接去参考官网样式,但主要是为了数值与样式,结构上没有必要完全照搬。它的轮播图大概可以划出以下几个层级:
- 大容器: 装下这个组件,100%的宽度
- 背景图: 随着轮播图的变化而变化,具体样式直接
F12 - 轮播图: 会有fade out的效果
- 左右的两个箭头:可以用
<与>,也可以把它的png下载下来用 - 下方的一排点:本以为是
div做的,没想到也是png - 右侧的广告,也是最烦人的,因为它的存在没法很好的把组件抽象出来(当然可以考虑加一个props的属性,从外部把这一坨给传入)
-
js逻辑:
- 定时切换
- 左右箭头:上一张与下一张
- 通过点击点来切换图片
- hover时暂停播放
-
传入组件的参数:
- 图片列表
- 播放周期
- 是否需要左右箭头
- 是否需要下方的点
-
然后可以采用
useState存储图片索引 -
然后考虑
useEffect这个hooks,而useEffect中放入计时器时需要一个依赖数组的引入,而这个数组中首先需要监听图片索引的变化,其次监听图片列表的变化(图片列表有可能是从后端取到的,在加载组件的时候很可能是空的,加载完成之后才会引入,为了避免出现bug) -
然后就发现悬停后移开鼠标轮播图依然不动,这是因为清除掉了定时器,而此时索引没有变,列表也没有变,
useEffect自然也就不会触发了,那么需要考虑再次引入一个值,当悬停时会改变状态
叨叨叨的文字扯完了,上代码,我的代码逻辑实现大致如下:
const Swiper = (props) => {
const {
picList,
cycle,
ifArrow,
ifDot,
} = props
const numPic = picList.length;
const list = Array.from(Array(numPic), (item, index) => index);
const [indexPic, setIndexPic] = useState(0);
const idTimer = useRef(0);
const [play, setPlay] = useState(true);
const nextImage = () => {
clearInterval(idTimer.current);
setIndexPic(indexPic => (indexPic + 1) % parseInt(numPic));
};
const lastImage = () => {
clearInterval(idTimer.current);
setIndexPic(indexPic => (indexPic + numPic - 1) % parseInt(numPic));
};
const pickPoint = (index) => {
clearInterval(idTimer.current);
setIndexPic(index);
};
const startSwiper = () => {
stopSwiper();
idTimer.current = setInterval(() => setPlay(!play), cycle);
};
const stopSwiper = () => {
clearInterval(idTimer.current);
};
useEffect(() => {
idTimer.current = setInterval(() => {
if (numPic > 0) {
nextImage();
}
}, cycle);
return () => {
clearInterval(idTimer.current);
}
// eslint-disable-next-line react-hooks/exhaustive-deps
}, [indexPic, numPic, play]);
return (
...
)
}
export default Swiper;
本文仅为兴起时随手而写的一点文字,如有纰漏不足,还请多多批评斧正