
React开发:reactHooks+ts(函数组件)实现原生轮播。
下载依赖(第一个是JS依赖,第二个是ts依赖)
npm install smoothscroll-polyfill --save npm i --save-dev @types/smoothscroll-polyfill
CSS文件
.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;
}
}
}
}创建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> ) }
试试吧!




网友评论文明上网理性发言 已有0人参与
发表评论: