使用Typescript+React hooks实现滑动点赞的组件
2021/8/7 23:08:09
本文主要是介绍使用Typescript+React hooks实现滑动点赞的组件,对大家解决编程问题具有一定的参考价值,需要的程序猿们随着小编来一起学习吧!
自从React推出hooks后,函数式组件好像可以配合hooks做任何事了,不用class component也能实现各种功能了,而且这种模式更加灵活,更易于拆分与封装。一番体验下来,充分意识到,函数式编程+hooks才是React的王道。今天我们就来使用hooks来实现一下滑动列表项显示点赞按钮的功能。页面如下所示:
梳理一下功能:滑动列表条目时,左滑显示点赞按钮,并且关掉其他条目的按钮显示;右滑,关掉当前条目的点赞按钮展示。
其实这个功能实现起来没有什么难度,只是给列表条目绑定touchmove事件,左滑的时候,添加样式,使条目左移,显示出点赞按钮。我们直接上代码看看:
// index.tsx import React from 'react'; import './index.less'; import { newsItem } from '../../types'; import useSwipe from '../../hooks/useSwiper'; const newsListData = [ { id: 1, title: '菲律宾多位学者发起网上请愿', src: 'pic.png', abstract: '菲律宾多位学者5日发起网上请愿活动,希望收集足够多的签名。', releaseDate: '2021-08-06 15:42', like: false, }, { id: 2, title: '引导粉丝文化步入健康轨道', src: 'pic1.png', abstract:'各相关方都要负起社会责任,坚持正确导向,自觉做社会正能量的放大器', releaseDate: '08-05 06:30', like: false, }, ]; function SwiperItem({ title, src, abstract, releaseDate, isCurrent, like, swipeEventHandler, likeEventHandler, }: newsItem) { return ( <div className="swiper-list-item" {...swipeEventHandler}> <div className={[ 'item-content-wrap', isCurrent ? 'swiper-left' : '', ].join(' ')} > <img className="news-pic" src={src} alt={title} /> <div className="item-right-content"> <p className="news-title">{title}</p> <p className="news-abstract">{abstract}</p> <p className="news-publish-date">发布时间:{releaseDate}</p> </div> </div> <div className="like-btn" {...likeEventHandler}> {like ? '取消' : '点赞'} </div> </div> ); } export default function SwiperList() { const { swipeList, createSwipeProps, createLikeProps } = useSwipe(newsListData); return ( <div className="swiper-list-cpn"> {swipeList.map((item) => ( <SwiperItem key={item.id} {...{ ...item, ...createSwipeProps(item.id), ...createLikeProps(item.id), }} /> ))} </div> ); }
// useSwipe.ts import { useState } from 'react'; import { newsItem } from '../types'; function setSwipeLeftList(list: Array<newsItem>, id: number): Array<newsItem> { return list.map((item) => ({ ...item, isCurrent: item.id === id, })); } function setSwipeRightList(list: Array<newsItem>): Array<newsItem> { return list.map((item) => ({ ...item, isCurrent: false, })); } function setLikeList(list: Array<newsItem>, id: number): Array<newsItem> { return list.map((item) => ({ ...item, like: item.id === id ? !item.like : item.like, })); } export default function useSwipe(list: Array<newsItem>) { const [swipeList, setSwipeList] = useState(list); const [preId, setPreId] = useState(-1); const [startX, setStartX] = useState(0); return { swipeList, createSwipeProps: (id: number) => { return { swipeEventHandler: { onTouchStart: (e: React.TouchEvent) => { // 滑动初始位置 setStartX(e.targetTouches[0].clientX); }, onTouchEnd: (e: React.TouchEvent) => { const endX = e.changedTouches[0].clientX; const deltaX = startX - endX; if (deltaX > 50) { // 左滑 if (id === preId) return; setSwipeList(setSwipeLeftList(swipeList, id)); setPreId(id); } else if (deltaX < -50) { // 右滑 if (id !== preId) return; setSwipeList(setSwipeRightList(swipeList)); setPreId(-1); } }, }, }; }, createLikeProps: (id: number) => { return { likeEventHandler: { onClick: () => { setTimeout(() => { setSwipeList(setLikeList(swipeList, id)); }, 100); }, }, }; }, }; }
// index.less .swiper-list-cpn { padding: 20px; .swiper-list-item { position: relative; height: 140px; margin-bottom: 20px; border-radius: 4px; overflow: hidden; box-shadow: 2px 2px 5px grey; .item-content-wrap { position: absolute; left: 0; top: 0; z-index: 1; display: flex; align-items: center; height: 100%; box-sizing: border-box; padding: 10px 20px; background: #fff; transition: transform 0.3s ease-in; &.swiper-left { transform: translateX(-60px); } .news-pic { width: 80px; margin-right: 20px; } .item-right-content { flex: 1; .news-title { margin-bottom: 10px; font-size: 16px; font-weight: bold; white-space: nowrap; overflow: hidden; text-overflow: ellipsis; } .news-abstract { margin-bottom: 10px; font-size: 14px; } .news-publish-date { font-size: 12px; color: grey; } } } .like-btn { position: absolute; right: 0; top: 0; width: 60px; line-height: 140px; text-align: center; background: rgb(255, 66, 66); } } }
看代码的结构的话,我把整个逻辑层抽离出来一个自定义hook,这个hook很简单,我的列表是根据列表的数据渲染出来的,所以其实我只需要跟列表的数据打交道就行了,不管是左滑右滑还是点赞取消点赞,都只是改变列表的数据内容,改变后再渲染到页面上。Hooks很强大,也很灵活,这既是优点也是缺点,如果你能很好进行模块的拆解与封装,那么代码的可读性和可维护性会很高,反之,简单的怼hooks,后期维护将是灾难。
这篇关于使用Typescript+React hooks实现滑动点赞的组件的文章就介绍到这儿,希望我们推荐的文章对大家有所帮助,也希望大家多多支持为之网!
- 2024-12-21Vue3教程:新手入门到实践应用
- 2024-12-21VueRouter4教程:从入门到实践
- 2024-12-20Vue3项目实战:从入门到上手
- 2024-12-20Vue3项目实战:新手入门教程
- 2024-12-20VueRouter4项目实战:新手入门教程
- 2024-12-20如何实现JDBC和jsp的关系?-icode9专业技术文章分享
- 2024-12-20Vue项目中实现TagsView标签栏导航的简单教程
- 2024-12-20Vue3入门教程:从零开始搭建你的第一个Vue3项目
- 2024-12-20从零开始学习vueRouter4:基础教程
- 2024-12-20Vuex4课程:新手入门到上手实战全攻略