共计 3768 个字符,预计需要花费 10 分钟才能阅读完成。
自从 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,前期保护将是劫难。
正文完