携手创作,共同成长!这是我参与「掘金日新计划 · 8 月更文挑战」的第1天,点击查看活动详情
大家好,我是佑子。有挺长时间没更掘金了(也没有人关注我,哈哈哈!!!)关于写这篇掘金的理由,可能有点长。所以我放在下面当个小前言吧在上个礼拜。感兴趣的可以看看
一.前言
1.为什么要写这篇文章
我从蚂蚁外包。跳到了字节跳动的外包(实在是进不去字节自研,我就是个菜鸡),虽然我简历上是写的两年半工作经验。但实际从培训班出来也就半年,去年年底来到杭州。在蚂蚁外包干了7个月,枯燥无味的生活促使我跳槽。
其实现在这个大环境(今天2022年8月1日),互联网行业并不好过。阿里裁员40%,字节招人名额减少,跳槽其实并不是一个明智之举。但我还是跳了,因为在蚂蚁外包是在太无聊了,基本上学不到东西,因为没人管你。虽然工资没涨,我也觉得可以了。毕竟自己其实只干了半年多一两个月,有什么资格要求涨工资呢,还是在环境不好的情况下,能找到工作就不错了。
进入字节这边。干的第一个需求,在进行code review的时候,就发现了自己在写代码的时候挺多不足的,也不是说某些地方不会写。就是代码写的好与不好的情况,代码的维护性和可读性上,并不是很好。所以特意来写一篇文章(也是因为需求干完了,是在太无聊了,旁边大佬都看着,只能敲敲键盘)
- 记录自己代码开发中,一些可以提高的点
- 便于以后自己查阅
- 分享给初入前端的小白们
二.正文
1.巧用截取数组的方法渲染页面
在我的需求中,需要渲染一个描述列表,代码如下,在这个需求里面,我需要动态判断客户是否有名字,来决定是否渲染名字。如果按下面这样写的话,我只需要判断下
import { Descriptions, Tag } from 'antd';
import React from 'react';
// 假设只是用户返回的数据
const user = {
haveName: true,
name: '张xx',
live: '浙江杭州',
remark: '',
}
const App: React.FC = () => (
<Descriptions title="User Info">
<Descriptions.Item label="是否有名字"><Tag>{user.haveName}</Tag></Descriptions.Item>
{ user.haveName && <Descriptions.Item label="名字">{user.name}</Descriptions.Item>}
<Descriptions.Item label="地址">{user.live}</Descriptions.Item>
<Descriptions.Item label="个性签名">{user.remark}</Descriptions.Item>
</Descriptions>
);
export default App;
但是这种写法,如果描述列表展示信息少的话,还好。如果描述列表信息多了以后,这个组件看起来其实是不太方便的。并且,描述列表里如果要展示标签,链接,table啥的。这个组件看起来就会更累。所以我把具体的列表信息抽离了出来,这样让组件可读性和维护性上得到提升。具体如下
// descList.js
export const descList = [
{
key: 'haveName',
value: '是否有名字',
render(val) {
return <Tag>{val}</Tag>
}
},
{
key: 'name',
value: '名字'
},
{
key: 'name',
value: '地址'
},
{
key: 'name',
value: '个性签名',
render(val) {
return val ? val : '该用户暂未填写个人签名'
}
},
]
// index.tsx
import { descList } from './descList.js'
import { Descriptions } from 'antd';
import React from 'react';
// 假设只是用户返回的数据
const user = {
haveName: true,
name: '张xx',
live: '浙江杭州',
remark: '123',
}
const App: React.FC = () => {
const desc = useMemo(()=>{
const copyDesc = [...descList]
if(obj.haveName) {
copyDesc.splice(1,1)
}
return copyDesc
},[obj])
return (
<Descriptions title="User Info">
{desc.map((item)=> (
<Descriptions.Item label={item.value}>
{item.render ? item.render(user[item.key]) : user[item.key]}
</Descriptions.Item>
))}
</Descriptions>
)};
export default App;
通过这样改写,我就能通过只改写descList文件,去修改展示的描述列表。从而不去动index里面的逻辑代码。但是细心的小伙伴应该发现了,这样写的话,我没法去判断haveName这个字段,只能通过splice去截取或者filter过滤(这里只展示splice方法的问题)。splice在这里其实有个问题。1.从可读性上来说,你后面某位同事改代码,第一眼并不知道去除的哪个元素,2.从维护性上来说,改了descList列表的话,如果没改index那个截取的序列号,就会导致页面展示的信息错误。所以这里我们需要去改写一下
const desc = useMemo(()=>{
const copyDesc = [...descList]
if(obj.haveName) {
copyDesc.splice(copyDesc.findIndex((e=>e.key === 'name')),1)
}
return copyDesc
},[obj])
通过上面改写,这样不论如何 都是截取的展示name那一项
2.去除项目中的magic数字
在step组件中,通常会有很多节点。我们需要根据后端返回的数据来返回一个status来提供他的当前信息。
// 假设后端给我们返回的数据
// passed 为0 代表拒绝 1代表已完成 2代表为开始
const nodes = [
{
key: '开始',
passed: 1
},
{
key: '人工审批',
passed: 0
},
{
key: '结束',
passed: 2
},
]
const App: React.FC = () => {
const getStatus = (passed) => {
if(passed === 0) {
return 'error'
} else if(passed === 1 ) {
return 'finish'
} else if(passed === 2 ) {
return 'process'
}
}
return (
<Steps current={1}>
{nodes.map((item)=> <Step title={item.key} status={getStatus(item.passed)}/>)}
</Steps>
)
};
上面我们判断passed 来返回对应的节点状态。但是不是自己写的功能的话,这个0,1,2几个数字,别人看不懂的。在代码里我们称为魔术数字,所以我们需要改写一下
// 定义一个映射关系
const NodePassMap = new Map([\
[0, 'error],
[1, 'finish'],
[2, 'process'],
]);
// 获取状态的函数就可以直接改为
const getStatus = (passed) => NodePassMap.get(node.Passed);
console.log(getStatus(0)) // 'error'
3.提供枚举文件说明数字含义
还是上面这个例子,但是有换了个场景,我们需要在passed为0的时候,展示一个特殊的icon
// 假设后端给我们返回的数据
// passed 为0 代表拒绝 1代表已完成 2代表为开始
const nodes = [
{
key: '开始',
passed: 1
},
{
key: '人工审批',
passed: 0
},
{
key: '结束',
passed: 2
},
]
const App: React.FC = () => {
const getIcon = (passed) => {
if(passed === 0) {
return { icon : <Icon type="home"/>}
}
return {}
}
return (
<Steps current={1}>
{nodes.map((item)=> <Step title={item.key} {...getIcon()} />)}
</Steps>
)
};
上面代码者 这个if判断这里 其实0的含义我们是不知道的,只能通过去询问后端或看之前代码。但是如果我们加一个枚举文件,就能很好的解决这个问题
type NodePassed = {
error: 0,
finish: 1,
process: 2
}
const getIcon = (passed) => {
if(passed === NodePassed.error) {
return { icon : <Icon type="home"/>}
}
return {}
}
相信大部分小伙伴,一看到这里,就会知道 原来error的时候,就展示这个图标
三.结语
写到这里,这篇文章算是结束了。其实文章里的所有代码,相信在座的各位都能写。但只是不知道应该这样写。这篇文章主要是为了教小白写出更漂亮的代码。大神轻点喷