1.三元表达式和if使用场景
// bad
if(n > 0) {
fn1()
} else {
fn2()
}
// good
n > 0 ? fn1() : fn2()
// bad 三元嵌套三元不利于可读性
let message = (age < 3) ? 'Hi, baby!' :
(age < 80) ? 'Hello!' :
'What an unusual age!';
// good
if (age < 3) {
message = 'Hi, baby!';
} else if (age < 80) {
message = 'Hello!';
} else {
message = 'What an unusual age!';
}
2.魔法值的问题
// bad 魔法值举例
if(flag === '5'){
.......
}
if (businessType === 101){
.......
}
//good 使用枚举
const BusinessTypeEnum = {
SYSTEM: 0, // 系统
CRM: 1, // CRM
JXC: 2, // JXC
UNKNOWN: 404, // 未知对象类型
CUSTOMER_MANAGEMENT: 100, // 客户管理
CUSTOMER: 101, // 客户
CUSTOMER_FOCUS: 102, // 重点客户
CUSTOMER_DEAL: 103, // 成交客户
CUSTOMER_FOLLOW: 104, // 跟进客户
CUSTOMER_PUBLIC: 105 // 客户公海池
}
if (businessType === BusinessTypeEnum.CUSTOMER){
.......
}
采用枚举的另外一个好处,当某个值因为需求迭代需求变更时,我们只需要在枚举中将该值替换,并不需要在全局搜素替换。
3.属性传递的问题
属性传递问题是一种常见的不良习惯,它发生在将属性从一个组件传递到多层嵌套的子组件时。这可能导致性能问题和代码可读性降低。理想情况下,应该尽量避免将属性传递超过2层。下面是一个示例:
// 父组件
function ParentComponent() {
const data = 'Some data';
return (
<ChildComponent data={data} />
);
}
// 子组件
function ChildComponent({ data }) {
return (
<GrandchildComponent data={data} />
);
}
// 孙子组件
function GrandchildComponent({ data }) {
// 使用数据
return <div>{data}</div>;
}
在上面的示例中,data属性通过多个嵌套层级传递,这可能导致性能问题和可读性问题。解决这个问题的方法之一是使用React的上下文(context)来共享数据,或者重新组织组件结构。
4.if嵌套的问题
以下代码是4层if-else嵌套的代码,即使已经将具体逻辑封装到一个个函数里边了,但还是看着费劲,更别说未封装的情况!
function fn(data) {
if (data !== null) {
if (data.num >= 5) {
fn2()
if (data.flag) {
fn3()
} else{
fn3Err()
}
} else if (data.num >= 0) {
fnErr2()
} else {
fnErr3()
}
} else {
fnErr()
}
}
改进方法:先处理坏情况,剩下的就是好情况,从而把横向嵌套层数降为1
function fn(data) {
if (data === null) return fnErr() // 1级坏情况:data为null
if (data.num < 0) return fnErr3() // 2级坏情况
if (data.num < 5) return fnErr2() // 2级坏情况
// 剩下的就是1级好情况了,即data !== null && data.num >= 5
fn2()
if (!data.flag) return fn3Err() // 3级坏情况
fn3()
// 或合并成一行: data.flag ? fn3() : fn3Err()
}
5.引入本地文件、三方文件
- 引入文件的顺序,一般依赖的库写在前面,本地文件写在后面,同类型的可以空格区分
- 避免冗余的引入
// js库
import { Fragment, useCallback, useEffect, useMemo, useState } from 'react';
import PropTypes from 'prop-types';
import { Box, Typography, Alert, TableContainer, TableBody, TableCell, TableHead, TableRow, Paper, Table } from '@mui/material';
import { useFormik } from 'formik';
import * as yup from 'yup';
import FormatMessage from 'intl-service';
import { useTheme } from '@mui/material/styles';
import EastIcon from '@mui/icons-material/East';
// 本地组件
import UAutocomplete from 'views/components/UAutocomplete';
import SelectList from 'views/components/SelectList';
// 本地js方法
import { fieldType } from 'utils/const';
import { underscoreToCamel } from 'utils/utils';
// API
import { GetCDPAttributes } from 'api/contacts';
6.减少重复计算
React组件可能会在不同时间点重新渲染,如果不小心,某些工作可能会在每次渲染时都重复执行,这会降低性能。为了避免这种情况,可以使用useMemo和useCallback来记忆化操作,以便它们不会在每次渲染时重新计算。以下是一个示例:
function List({ items }) {
// 不使用useMemo - 每次渲染都会重新过滤
const filteredItems = items.filter(item => item.active);
// 使用useMemo - 只在items发生变化时重新过滤
const filteredItems = useMemo(() => items.filter(item => item.active), [items]);
}
7.业务逻辑与组件逻辑分离
在React中,尽量将业务逻辑与UI组件逻辑分开,以提高代码的可读性和可维护性。将业务逻辑提取到独立的服务文件或模块中,以使组件保持简单。以下是一个示例:
// 不良示例 - 业务逻辑混杂在组件中
function UserProfile() {
const user = getUserData(); // 从API获取用户数据
return (
<div>
<h1>{user.name}</h1>
<p>{user.email}</p>
</div>
);
}
// 良好示例 - 业务逻辑分离
function UserProfile() {
const user = useUserData(); // 从独立服务获取用户数据
return (
<div>
<h1>{user.name}</h1>
<p>{user.email}</p>
</div>
);
}