一、场景描述
我想写一个轮播图的程序,只是把bootstrap里面的轮播图拉过来就用上感觉不是很合适,然后我就想自己写自动轮播,因此,这篇文章里面只是自动轮播的部分,没有按键跟自动轮播的衔接部分。
Ps: 本文用的是函数式组件,因为新版本的react函数式组件用的比较多。
二、相关知识
2.1 怎么在react.js中使用bootstrap
首先,在react中引入bootstrap。
npm install bootstrap
然后在index.js中引入bootstrap,在后续组件中使用bootstrap的时候就不需要再引入。
需要同时引入css文件和js文件。
import "bootstrap/dist/css/bootstrap.min.css";
import "bootstrap/dist/js/bootstrap";
2.2 useEffect钩子
useEffect钩子是在渲染之后运行的程序。有一个作用是:根据React state控制非React组件。
在部分的内容中有三种写的方式:
useEffect(() => {
//代码
// eslint-disable-next-line react-hooks/exhaustive-deps
}, []); //后面的依赖数据是空的,就是只在第一次渲染的时候运行
useEffect(() => {
//代码
// eslint-disable-next-line react-hooks/exhaustive-deps
}); //后面没有依赖,每次渲染的时候都会运行
useEffect(() => {
//代码
// eslint-disable-next-line react-hooks/exhaustive-deps
},[img]); //后面的依赖是img就只在img改变的时候再运行
2.3useRef钩子
ref和state之间的区别在于state变化之后组件会重新渲染,ref变化之后组件不会重新渲染。ref在整个组件生命周期内保持不变。
import { useRef } from "react”;
let currentIndex1 = useRef(0); //定义ref
//html中代码
<button onClick={() => {
console.log(currentIndex1.current);
currentIndex1.current = currentIndex1.current + 1;
}}>+1</button>
三、轮播图的自动播放功能实现
这部分分为两个问题,一个是自动播放的index,自动播放就是定时器interval;另一个是通过class类定义当前显示的图片,然后设置动画。
这里定义index只能是state,因为ref变化不会渲染,这样根据index改变的class类可能就改变不了。
思路如下图所示。
整体代码如下:
Recommend.tsx
import { useRef } from "react";
import React, { useEffect, useState } from "react";
import hyRequest from "../../service/index";
const Recommend = function () {
const [img, setImg] = useState<any[]>([]);
let currentIndex1 = useRef(0);
const [currentIndex, setCurrentIndex] = useState(0);
useEffect(() => {
hyRequest.get({ url: "/banner" }).then((res) => {
console.log(res);
setImg(res.banners);
console.log(img);
});
// eslint-disable-next-line react-hooks/exhaustive-deps
}, []);
useEffect(() => {
console.log("设置定时器");
const interval = setInterval(() => {
//console.log(img, img.length);
//currentIndex.current = (currentIndex.current + 1) % img.length;
//console.log(currentIndex.current);
setCurrentIndex((preCurrentIndex) => (preCurrentIndex + 1) % img.length);
}, 3000);
return () => clearInterval(interval); // 清除定时器
// eslint-disable-next-line react-hooks/exhaustive-deps
}, [img]);
return (
<div>
<h2>推荐</h2>
<div id="carouselExample" className="carousel slide">
<div className="carousel-inner">
{img.map((item, index) => {
//console.log(currentIndex, item, index);
return (
<div
key={index}
className={`carousel-item ${
index === currentIndex ? "active" : ""
} ${index === currentIndex - 1 ? "preActive" : ""} ${
index === currentIndex + 1 ? "nextActive" : ""
}`}
>
<img src={item.imageUrl} className="d-block w-100" alt="..." />
</div>
);
})}
</div>
<button
className="carousel-control-prev"
type="button"
data-bs-target="#carouselExample"
data-bs-slide="prev"
>
<span
className="carousel-control-prev-icon"
aria-hidden="true"
></span>
<span className="visually-hidden">Previous</span>
</button>
<button
className="carousel-control-next"
type="button"
data-bs-target="#carouselExample"
data-bs-slide="next"
>
<span
className="carousel-control-next-icon"
aria-hidden="true"
></span>
<span className="visually-hidden">Next</span>
</button>
</div>
<div>{currentIndex1.current}</div>
<button
onClick={() => {
console.log(currentIndex1.current);
currentIndex1.current = currentIndex1.current + 1;
}}
>
+1
</button>
</div>
);
};
export default Recommend;
index.less
.nextActive {
display: block !important;
transform: translateX(100%);
opacity: 0;
}
.active {
transform: none;
opacity: 1;
}
.preActive {
display: block !important;
transform: translateX(-100%);
opacity: 0;
}