ReactHooks+ts(函数组件)实现原生轮播的示例

 更新时间:2022年05月30日 16:48:28   作者:燕京拾亿  
这篇文章主要介绍了ReactHooks+ts函数组件实现原生轮播,在这里下载依赖第一个是js依赖第二个是ts依赖,通过实例代码介绍了创建tsx文件的方法,需要的朋友可以参考下

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轮播内容请搜索脚本之家以前的文章或继续浏览下面的相关文章希望大家以后多多支持脚本之家!

相关文章

  • 基于JavaScript实现无限加载瀑布流

    基于JavaScript实现无限加载瀑布流

    这篇文章主要为大家详细介绍了基于JavaScript实现无限加载瀑布流,具有一定的参考价值,感兴趣的小伙伴们可以参考一下
    2017-07-07
  • 浅谈webpack构建工具配置和常用插件总结

    浅谈webpack构建工具配置和常用插件总结

    这篇文章主要介绍了浅谈webpack构建工具配置和常用插件总结,小编觉得挺不错的,现在分享给大家,也给大家做个参考。一起跟随小编过来看看吧
    2020-05-05
  • JavaScript中this的四个绑定规则总结

    JavaScript中this的四个绑定规则总结

    相信大家都知道,ES5及之前时代的JavaScript中this的绑定机制是让很多开发者头疼不已的事情。this 的绑定变化多端,让笔者也吃了不少亏。所以本文总结了this的四条绑定规则,在此记录,以防自己遗忘,也方便他人参考借鉴。下面来一起看看吧。
    2016-09-09
  • JavaScript事件处理的方式(三种)

    JavaScript事件处理的方式(三种)

    最近这段时间因为每天要修改网站,为网站做特效,所以看了很多的js接触事件,自己只会使用一小部分,有时用的时候也比较混乱,现在系统的整理了一下,特此分享到脚本之家平台供大家参考下
    2016-04-04
  • Bootstrap Table中的多选框删除功能

    Bootstrap Table中的多选框删除功能

    这篇文章主要介绍了Bootstrap Table中的多选框删除功能,非常不错,具有一定的参考借鉴价值,需要的朋友可以参考下
    2018-07-07
  • uniapp在微信小程序中使用ECharts的方法

    uniapp在微信小程序中使用ECharts的方法

    本文主要介绍了uniapp集成Echarts,实现地图图表的展示,文中通过示例代码介绍的非常详细,需要的朋友们下面随着小编来一起学习学习吧
    2021-06-06
  • js对url进行编码解码的三种方式总结

    js对url进行编码解码的三种方式总结

    为一个字符串进行URL编码很容易,只需要调用encodeURI,传入要编码的字符串即可,而且实现的方法不止这一个,下面这篇文章主要给大家介绍了关于js对url进行编码解码的三种方式,需要的朋友可以参考下
    2023-02-02
  • JS锚点的设置与使用方法

    JS锚点的设置与使用方法

    这篇文章主要介绍了JS锚点的设置与使用方法,涉及javascript针对页面元素属性的简单动态操作技巧,需要的朋友可以参考下
    2016-09-09
  • javascript下有关dom以及xml节点访问兼容问题

    javascript下有关dom以及xml节点访问兼容问题

    javascript下有关dom以及xml节点访问兼容问题...
    2007-11-11
  • 使用JavaScript制作待办事项列表的示例代码

    使用JavaScript制作待办事项列表的示例代码

    这篇文章主要介绍了如何使用 JavaScript创建待办事项列表HTML的完整信息和教程,文中但是示例代码讲解详细,感兴趣的同学可以动手试一试
    2022-01-01

最新评论