使用常量
将一些约定好的内容用常量表示,方便统一修改和语义化,常量命名全部大写,单词间用下划线隔开,力求语义表达完整清楚,不要嫌名字长。
ts
export const BASE_URL = '/api/v1'
使用枚举值
使用枚举值可以减少代码中的魔法数字/字符,也可以避免js中的很多隐式类型转换。看看下面的场景
- 复用表单,例如一个新增和修改的表单往往都是一样的,只有少部分的表单有差异
tsx
import { Button, Form, Input, Select } from "antd";
import type { FC } from "react";
export const enum FormMode {
CREATE = "CREATE",
EDIT = "EDIT",
}
export const enum Jobs {
FE = "FE",
BE = "BE",
}
interface FormData {
username: string;
nickname: string;
job: Jobs;
}
interface IUserFormProps {
formMode: FormMode;
initValues?: FormData;
}
const UserForm: FC<IUserFormProps> = ({ formMode, initValues }) => {
const [form] = Form.useForm<FormData>();
const handleSubmit = (values: FormData) => {
if (formMode === FormMode.CREATE) {
create(values);
} else {
update(values);
}
};
return (
<Form form={form} onFinish={handleSubmit}>
<Form.Item label="用户名" name="username">
<Input />
</Form.Item>
<Form.Item label="昵称" name="nickname">
<Input />
</Form.Item>
<Form.Item label="岗位" name="job">
<Select>
<Select.Option value="FE">前端</Select.Option>
<Select.Option value="BE">后端</Select.Option>
</Select>
</Form.Item>
<Button type="primary" htmlType="submit">
保存
</Button>
{formMode === FormMode.EDIT && <Button danger>删除</Button>}
</Form>
);
};
export default UserForm;
- 权限相关
ts
enum RoleType {
ADMIN, //默认第一个为 0,可以根据服务端返回自定义
EDITOR,
GUEST
}
枚举的写法可以自己定一个规范,如果使用的是 js 可以使用 object 代替。 细心的小伙伴可能发现了,我们使用 typescript 的 enum
时候是 const enum
而不是 enum
, 因为使用 const enum 可以减少编译后的 JavaScript 文件大小,因为它不会引入额外的对象和代码。适合在编译后不需要保留枚举对象,而仅需使用枚举值的情况。而适合在需要在运行时保留枚举对象,并且需要对枚举进行更多操作的情况。
ts
export const enum FormMode {
CREATE = "CREATE",
EDIT = "EDIT",
}
console.log(FormMode.CREATE);
console.log(FormMode.EDIT);
//编译后的
console.log("CREATE");
console.log("EDIT");
ts
export enum FormMode {
CREATE = "CREATE",
EDIT = "EDIT",
}
console.log(FormMode.CREATE);
console.log(FormMode.EDIT);
//编译后的
var FormMode;
(function (FormMode) {
FormMode["CREATE"] = "CREATE";
FormMode["EDIT"] = "EDIT";
})(FormMode || (FormMode = {}));
console.log(FormMode.CREATE);
console.log(FormMode.EDIT);
简单来说如果你需要使用枚举值做一些操作 如const obj = {...FormMode}
就需要使用 enum
,反之使用const enum
减少编译后代码。
使用 Map 代替 一些简单的switch-case
ts
function calculate(operator, num1, num2) {
let result;
switch (operator) {
case '+':
result = num1 + num2;
break;
case '-':
result = num1 - num2;
break;
case '*':
result = num1 * num2;
break;
case '/':
result = num1 / num2;
break;
default:
result = 'Invalid operator';
}
return result;
}
console.log(calculate('+', 5, 3)); // 输出 8
使用Map,使用 object 也一样
ts
function calculate(operator, num1, num2) {
const operations = new Map([
['+', (a, b) => a + b],
['-', (a, b) => a - b],
['*', (a, b) => a * b],
['/', (a, b) => a / b],
]);
const operation = operations.get(operator);
if (operation) {
return operation(num1, num2);
} else {
return 'Invalid operator';
}
}
console.log(calculate('+', 5, 3)); // 输出 8
合理使用变量/函数
好的代码不需要注释 这是编程中一个比较有争议的说法,但是我们写代码的过程中确实有一些操作可以通过这种方式减少注释,写出更干净更容易维护的代码。
- 复杂的判断
ts
// 游客可以访问未过期的公开项目
if(RoleType===RoleType.GUEST&&ProjectType === ProjectType.PUBLIC&&project.expires){
return true
}
const isPublicGuestViewable = RoleType===RoleType.GUEST&&ProjectType === ProjectType.PUBLIC&&project.expires
if(isPublicGuestViewable){
return true
}
- 将一些操作抽象成函数 场景将 数组 arr1 中最大的数 和 arr2 中最小的数相加
ts
// bad
const arr1 = [1, 2, 3];
const arr2 = [1, 2, 3];
let max = arr1[0];
for (let i = 1; i < arr1.length; i++) {
if (arr1[i] > max) {
max = arr1[i];
}
}
let min = arr2[0];
for (let i = 1; i < arr2.length; i++) {
if (arr2[i] < min) {
min = arr2[i];
}
}
const result = min + max
// good
const arr1 = [1, 2, 3];
const arr2 = [1, 2, 3];
const max = findMax(arr1)
const min = findMin(arr2)
const result = min + max
function findMin(arr){...}
function findMax(arr){...}
减少函数的副作用,一个函数只做一件事情,这样写出来的代码更利于维护和单元测试。
ts
// bad
function findMaxOrMin(arr, type) {
let result = arr[0];
if (type === "min") {
for (let i = 1; i < arr.length; i++) {
if (arr[i] < result) {
result = arr[i];
}
}
} else {
...
}
return result;
}
类内方法的定义顺序
类内方法定义顺序依次是:公有方法或保护方法 > 私有方法 > getter/setter方法。
因为公有方法是类的调用者和维护者最关心的方法,首屏展示最好;保护方法虽然只是子类关心,也可能是"模板设计模式"下的核心方法;而私有方法外部一般不需要特别关心,是一个黑盒实现;因为承载的信息价值较低,所有Service和DAO的getter/setter方法放在类体最后。