自从React推出hooks后,函数式组件如同能够配合hooks做任何事了,不必class component也能实现各种性能了,而且这种模式更加灵便,更易于拆分与封装。一番体验下来,充沛意识到,函数式编程+hooks才是React的王道。明天咱们就来应用hooks来实现一下滑动列表项显示点赞按钮的性能。页面如下所示:

梳理一下性能:滑动列表条目时,左滑显示点赞按钮,并且关掉其余条目标按钮显示;右滑,关掉以后条目标点赞按钮展现。

其实这个性能实现起来没有什么难度,只是给列表条目绑定touchmove事件,左滑的时候,增加款式,使条目左移,显示出点赞按钮。咱们间接上代码看看:

// index.tsximport 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.tsimport { 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,前期保护将是劫难。