在前端开发工作中,一些微小但对代码提升巨大的点的总结(写给小白和一两年前端工作经验者)

6,805 阅读5分钟

携手创作,共同成长!这是我参与「掘金日新计划 · 8 月更文挑战」的第1天,点击查看活动详情

大家好,我是佑子。有挺长时间没更掘金了(也没有人关注我,哈哈哈!!!)关于写这篇掘金的理由,可能有点长。所以我放在下面当个小前言吧在上个礼拜。感兴趣的可以看看

一.前言

1.为什么要写这篇文章

我从蚂蚁外包。跳到了字节跳动的外包(实在是进不去字节自研,我就是个菜鸡),虽然我简历上是写的两年半工作经验。但实际从培训班出来也就半年,去年年底来到杭州。在蚂蚁外包干了7个月,枯燥无味的生活促使我跳槽。

其实现在这个大环境(今天2022年8月1日),互联网行业并不好过。阿里裁员40%,字节招人名额减少,跳槽其实并不是一个明智之举。但我还是跳了,因为在蚂蚁外包是在太无聊了,基本上学不到东西,因为没人管你。虽然工资没涨,我也觉得可以了。毕竟自己其实只干了半年多一两个月,有什么资格要求涨工资呢,还是在环境不好的情况下,能找到工作就不错了。

进入字节这边。干的第一个需求,在进行code review的时候,就发现了自己在写代码的时候挺多不足的,也不是说某些地方不会写。就是代码写的好与不好的情况,代码的维护性和可读性上,并不是很好。所以特意来写一篇文章(也是因为需求干完了,是在太无聊了,旁边大佬都看着,只能敲敲键盘)

  1. 记录自己代码开发中,一些可以提高的点
  2. 便于以后自己查阅
  3. 分享给初入前端的小白们

二.正文

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的时候,就展示这个图标

三.结语

写到这里,这篇文章算是结束了。其实文章里的所有代码,相信在座的各位都能写。但只是不知道应该这样写。这篇文章主要是为了教小白写出更漂亮的代码。大神轻点喷