ReactHooks+ts(函数组件)实现原生轮播的示例
短信预约 -IT技能 免费直播动态提醒
1.下载依赖(第一个是js依赖,第二个是ts依赖)
npm install smoothscroll-polyfill --save
npm i --save-dev @types/smoothscroll-polyfill
2.创建tsx文件
import React, { useRef, useState, useEffect } from 'react'
import './index.less'
import smoothscroll from 'smoothscroll-polyfill'
interface List {
id: string,
text: string
}
export default () => {
const [ButtonList] = useState<List[]>(
[
{
id: 'n1',
text: '推荐'
},
{
id: 'n2',
text: '女装'
},
{
id: 'n3',
text: '运动'
},
{
id: 'n4',
text: '美妆'
},
{
id: 'n5',
text: '男装'
},
{
id: 'n6',
text: '鞋靴'
},
{
id: 'n7',
text: '数码'
},
{
id: 'n8',
text: '母婴'
},
{
id: 'n9',
text: '家电'
},
{
id: 'n10',
text: '国际'
},
]
);
const [ContentList] = useState<List[]>(
[
{
id: 'c1',
text: '推荐'
},
{
id: 'c2',
text: '女装'
},
{
id: 'c3',
text: '运动'
},
{
id: 'c4',
text: '美妆'
},
{
id: 'c5',
text: '男装'
},
{
id: 'c6',
text: '鞋靴'
},
{
id: 'c7',
text: '数码'
},
{
id: 'c8',
text: '母婴'
},
{
id: 'c9',
text: '家电'
},
{
id: 'c10',
text: '国际'
},
]
);
// ref
const navLine = useRef<HTMLDivElement>(null)
const tabRef = useRef<HTMLDivElement>(null)
const navListParent = useRef<HTMLDivElement>(null)
const contentScrollWrap = useRef<HTMLDivElement>(null)
const GetContentScrollWrap = () => {
return contentScrollWrap.current as HTMLDivElement
}
const GetTabRef = () => {
return tabRef.current as HTMLDivElement
}
const GetNavLine = () => {
return navLine.current as HTMLDivElement
}
const GetNavListPart = () => {
return navListParent.current as HTMLDivElement
}
// 变量
let swiperStartX: number = 0
let swiperMoveX: number = 0
let num: number = 0
let date: number = 0
let startX: number = 0
let flag: boolean = false
// 状态
const [Index, setIndex] = useState<number>(0)
const [swiperItemWidth, setContentListWidth] = useState<number>(0)
const [tabItemWidth, setNavListWidth] = useState<number>(0)
const Cut = (key: number) => {
setIndex(key);
}
const FnStart = (e: React.TouchEvent) => {
date = Date.now()
num = 0
GetContentScrollWrap().style.transition = 'none'
swiperStartX = GetContentScrollWrap().offsetLeft - e.changedTouches[0].pageX;
startX = e.changedTouches[0].pageX;
GetContentScrollWrap().ontouchmove = FnMove;
}
const FnMove = (e: TouchEvent) => {
swiperMoveX = e.changedTouches[0].pageX;
if (num === 0) {
flag = true
}
num++
if (GetContentScrollWrap().offsetLeft > 0 || GetContentScrollWrap().offsetLeft < -swiperItemWidth * (ButtonList.length - 1)) return false
if (flag) {
GetContentScrollWrap().style.left = swiperMoveX + swiperStartX + 'px'
GetContentScrollWrap().ontouchend = FnEnd;
}
}
const FnEnd = (e: TouchEvent) => {
flag = false;
// let num = Index
GetContentScrollWrap().style.transition = 'left .3s linear'
if (Math.abs(startX - e.changedTouches[0].pageX) > swiperItemWidth / 2 || Date.now() - date < 300) {
// if (startX - e.changedTouches[0].pageX < 0) {
// if (Index > 0) {
// num = Index - 1
// } else {
// num = 0
// }
// } else if (Index + 1 > ButtonList.length - 1) {
// num = ButtonList.length - 1
// } else {
// num = Index + 1
// }
// setIndex(num)
setIndex(startX - e.changedTouches[0].pageX < 0 ? Index > 0 ? Index - 1 : 0
: Index + 1 > ButtonList.length - 1 ? ButtonList.length - 1 : Index + 1)
}
GetContentScrollWrap().style.left = -Index * swiperItemWidth + 'px'
GetContentScrollWrap().ontouchmove = null;
GetContentScrollWrap().ontouchend = null;
}
// 监听Index
useEffect(() => {
let lineTo = tabItemWidth * Index;
GetNavLine().style.transform = `translate3d(${lineTo}px,0,0)`;
GetNavLine().style.transition = '.1s';
//控制tab滚动
let tabTo = lineTo - tabItemWidth;
GetTabRef().scrollTo({ left: tabTo, behavior: "smooth" });
GetTabRef().style.transition = '.5s';
// 控制swiper滚动
let swiperTo = swiperItemWidth * Index;
GetContentScrollWrap().style.left = -swiperTo + 'px';
GetContentScrollWrap().style.transition = '.5s';
}, [Index]);
// 解决移动端 scrollTo 的 behavior: "smooth" 无效的问题
useEffect(() => {
smoothscroll.polyfill();
// swiper元素宽度
setContentListWidth((GetContentScrollWrap().children[0] as HTMLDivElement).offsetWidth)
// nav列表宽度
setNavListWidth((GetNavListPart().children[0] as HTMLDivElement).offsetWidth)
}, [])
return (
<div className="v-home-wrap">
<div className='nav-wrap' ref={tabRef}>
<div className="nav" ref={navListParent}>
{ButtonList.map((item, index) =>
<div key={item.id} onClick={() => Cut(index)} className={Index === index ? "nav-list ac" : "nav-list"}>{item.text}</div>
)}
<div className="nav-line" ref={navLine}></div>
</div>
</div>
<div className="content-wrap">
<div className="content" onTouchStart={FnStart} ref={contentScrollWrap}>
{ContentList.map((item, index) =>
<div className='content-list' key={item.id}>{item.text}</div>
)}
</div>
</div>
</div>
)
}
3.创建less文件
.v-home-wrap {
touch-action: none;
.nav-wrap {
width: 100%;
overflow-x: scroll;
background: #f74077;
.nav {
padding: 0 20px;
display: flex;
align-items: center;
justify-content: space-between;
// min-width: 132vw;
color: #fff;
position: relative;
height: 82px;
.nav-list {
// box-sizing: border-box;
display: inline-block;
font-size: 28px;
padding: 0 18px;
min-width: 75px;
}
.nav-list.ac {
font-size: 34px;
}
.nav-line {
position: absolute;
width: 40px;
height: 6px;
background-color: #f9e2e8;
border-radius: 2px;
left: 45px;
bottom: 0;
// transition: all 1s;
}
}
}
.nav-wrap::-webkit-scrollbar {
display: none;
}
.content-wrap {
// overflow-x: scroll;
overflow: hidden;
height: 70vh;
position: relative;
left: 0;
.content {
min-width: 1000%;
display: flex;
height: 80vh;
// overflow-x: scroll;
position: absolute;
.content-list {
// white-space:nowrap;
// display: inline-block;
height: 80vh;
// overflow-y: scroll;
width: 100vw;
font-size: 50px;
text-align: center;
color: #fff;
}
.content-list:nth-child(2n) {
background: red;
}
.content-list:nth-child(2n-1) {
background: blue;
}
}
}
}
到此这篇关于ReactHooks+ts(函数组件)原生轮播的文章就介绍到这了,更多相关ReactHooks轮播内容请搜索编程网以前的文章或继续浏览下面的相关文章希望大家以后多多支持编程网!
免责声明:
① 本站未注明“稿件来源”的信息均来自网络整理。其文字、图片和音视频稿件的所属权归原作者所有。本站收集整理出于非商业性的教育和科研之目的,并不意味着本站赞同其观点或证实其内容的真实性。仅作为临时的测试数据,供内部测试之用。本站并未授权任何人以任何方式主动获取本站任何信息。
② 本站未注明“稿件来源”的临时测试数据将在测试完成后最终做删除处理。有问题或投稿请发送至: 邮箱/279061341@qq.com QQ/279061341