作者:@墨绶(wangyuezhou.wyz) 时间:2022-05-30
1 功能图
2 工作回顾
2.1 我的成长值
这个页面东西比较多比较散,所以抽成了三个组件来实现,头部、主要内容、尾部。总体要讲的就是,在数据加载完之前,用户看到的是loading界面,完成之后转入正常显示页面,如果失败,直接跳转ErrorPage。
2.1.1 头部
头部首先是一些基础数据的渲染,随后紧接着就是第一个小组件—进度条,进度条将墨卷的版本拿来加了点东西,做成了自己的pro版,主要用css来进行实现。大概实现了几个功能,第一次加载以及后续值发生变化时,可以有动画效果,在值当前位置,有一个闪烁光点。
.my-progress-bar {.bar-container {width: 100%;height: 100%;min-height: 12px;background-color: rgba(255, 255, 255, 0.4);border-radius: 25px;position: relative;.bar-fill {position: absolute;height: 100%;left: 0;top: 0;background-color: rgba(255, 255, 255, 0.8);border-radius: 25px;transition: width 0.6s ease;text-align: right;line-height: 30px;}.bar-fill::after {position: absolute;top: 50%;right: 2px;transform: translateY(-50%);content: '';width: 0;height: 0;z-index: 999;opacity: 0.6;animation: flickering 2s ease-in-out infinite;}}}@keyframes flickering {0% {box-shadow: 0 0 15px 5px #fff;}50% {box-shadow: 0 0 15px 7px #fff;}100% {box-shadow: 0 0 15px 5px #fff;}}
下面又是一些通过后端请求来的数据,没啥难度。
再后面是一个收缩卡片,主要分成会隐藏部分和下面的固定部分,上半会隐藏部分用一个参数showGrowthDetail来进行控制,但也是这种实现形式,导致无法做消失动画,有待优化。内部是一些静态数据,请求到后渲染即可,有个收起/展开操作用absolute进行绝对定位,并通过状态改变文本等。
进度圈是下一个抽离的小组件,基于antd的组件实现,通过em大致实现了自适应,但是在特定分辨率下还是会奇奇怪怪。
<ProgressCircle
percent={percent}
style={{
'--track-width': '5px',
'--fill-color': options.colorFill,
'--track-color': options.colorTrack,
'--size': options.size,
}}
>
<div className={styles['circle-info']}>
{options.numberInCircle}
<div className={styles['circle-footer']}>
{options.contentInCircle}
<div className={styles['jump-icon']} />
</div>
</div>
</ProgressCircle>
2.1.2 主要内容
这部分主要是数据的渲染,通过sessionStrorage / localStorage / api直接请求等多种形式最终得到渲染所需数据,花费了不少的时间,获取完成后用.map遍历渲染即可。
值得一提的是该部分的交互功能,当用户点击“去完成”等未完成的按钮时,界面将全局进行回应。首先,当前卡片中的进度条以及下方文本需要对应修改,这一部分可以用useState修改后会重新渲染的特点直接解决。其次是外层组件,由于没有全局静态,我采用了useContext,在最外层createContext之后,传入操作函数,内层只需传入需要改变的值即可完成子传父的传参。这一部分完成后,对应修改的所有部分,均重新加载动画(包括数值滚动动画)。
export const memberDataContext = createContext<any>({});
const changeData = (addPoints: number) => {
setMemberData({ ...memberData, myPoints: addPoints + memberData.myPoints });
};
<memberDataContext.Provider value={{ changeData }}>
// 。。。
</memberDataContext.Provider>
onClick={() => {
if (barData.numberNow < barData.numberMax) {
setCardData({
...cardData,
numberNow: cardData.numberNow + 100,
status: Number(cardData.numberMax === cardData.numberNow + 100),
});
memberData.changeData(100);
}
}}
2.1.3 尾部
2.2 成长值历史
样式不是很难,很快就搭好了,要做的就是实现无限下拉以及到底的判断。
这里骁博哥本意是让我们自己封装,但是我直接用了antd的现成组件,但是我还是自己去实现了一下到底判断的逻辑,通过在加载新一批数据时对剩余数据进行判断,若已经没有,则把hasMore属性改成false,则下次组件不再刷新。
const loadMore = async () => {
const historyList: IGrowthHistoryItemProps[] = [];
while (memberData.growthValue.detailList.length > 0 && count < 10) {
const shiftObject = memberData.growthValue.detailList.shift();
const pendingPushObject: IGrowthHistoryItemProps = {
title: shiftObject.title,
time: new Date(Number(shiftObject.date)).toLocaleString(),
changeAmount: shiftObject.count,
};
if (shiftObject.detail) {
pendingPushObject.content = shiftObject.detail;
}
historyList.push(pendingPushObject);
}
count = 0;
// setHasMore(memberData.growthValue.detailList.length > 0);
setGrowthHistoryData((pre) => {
return [...pre, ...pre];
});
};
2.3 不足
- 进度条样式不够细致,例如在进度条最后🈶️小黑点我没有实现
- 交互功能虽然能够基本完成状态判断以及数据的全局修改,但对于获取后升级等情况没有实现
3 结果
| 内容 | 完成情况 | 备注 | | —- | —- | —- | | 我的成长值 |
| | | — 头部 | 90% | 收缩卡片动画未实现 | | — 主要内容 | 100% |
| | — 尾部 | 100% |
| | 成长值历史 | 100% | |
4 项目总结
感觉比上次写的好多了,写多了后对ts、react等等都越来越熟悉,常见的几种hook也都知道该怎么用了,这次算是有几个部分写的自己挺爽的,比如用户交互那里,点击之后当前卡片内的数据修改,全局分数修改,进度条展示动画等等一连串响应,就很帅!
当然自己进度空间还是非常大的,强者几天就写完开始到处逛了,我还在那默默敲代码,还是要继续提升自己的实力,提高写代码的效率。
5 培训总结
这一个月感觉非常充实,因为基础不是很好,这一个月提升非常大。
首先,这是我第一次接触react和ts,从0到1虽然不好学,但是学会一门新的技术还是很爽的,然后,我熟悉了工作的流程,知道了怎么跟别人协作,熟悉了git操作,体验了pc端和移动端两端的项目,知道了自己哪部分还欠缺方便后面补上。
