2022年1-2月工作总结
React
数据透传,虽然使用了 props 进行层层传递,但是应该使用 context 进行透传。
避免过度使用 redux。
TypeScript
Array.includes
参考链接:https://fettblog.eu/typescript-array-includes/
export const ArrayUtils = {
includes<T extends U, U>(arr: ReadonlyArray<T>, el: U): el is T {
return arr.includes(el as T);
},
} as const;
工具函数
使用子集与超集进行对比,因为后端传值和前端传给后端的数据存在些微差异,后端可能会多传一些值,所以利用这个方法进行对比,判断共同的属性值是否相同。
如果两个对象的属性相同只用比较值是否相同,可以使用 loadsh 的 isEqual 函数
type BaseValue = { [key: string]: string[] | number[] | string | number };
/**
* 判断不相等,只判断相交的对象属性值是否相同,会深度对比每个对象中的属性值
* @param base 子集
* @param other 超集
* @returns
*/
export const isDiffByPart = <
T extends { [key: string]: string[] | number[] | string | number | BaseValue }
>(
base: T,
other: T
): boolean => {
return Object.keys(base).some((key) => {
const baseItem = base[key];
const otherItem = other[key];
if (baseItem && otherItem && !isEqual(baseItem, otherItem)) {
if (typeof baseItem !== typeof otherItem) {
return true;
}
if (typeof baseItem === 'number' || typeof baseItem === 'string') {
return true;
}
if (
typeof baseItem === 'object' &&
typeof otherItem === 'object' &&
baseItem?.length === otherItem?.length
) {
return isDiffByPart(baseItem as T, otherItem as T);
}
return true;
}
return false;
});
};
总结与反思
组件
- 将重复的组件抽出来,可以做一些 UI 组件。
CR 问题
文件嵌套过深,多个同名文件容易产生代码的理解成本。如果是一个页面的常量和类型尽量写在一个文件中,避免一个目录下一个常量和类型文件。
一般来讲在页面这一级集中处理下面组件、常量、和工具方法可以满足大部分需求,更方便统一维护。
相对路径层级过深应使用绝对路径进行替换。
思想
有一点点对项目中引入 npm 包有点抵触和抗拒,会觉得容易引入麻烦或者说无用的包,后期还要优化掉的包,从而使用了很奇怪的代码写法,虽然奇怪的代码写法在后期重新改了,但是初期的代码设计还有有点糟糕。
因为推崇使用 await-to-js 库,但是又觉得没有必要专门导入这个库进来。所以使用了比较 hack 的方式:在 promise 函数返回的时候手动返回 [error, res] 格式,这样增加了代码理解成本,不能一下子 get 到为什么要这样写以及这样写的背景。
Await-to-js 库主要是为了避免 try-catch 地狱的问题(就是 try-catch 使用的太多了)
// shit code
// 想的是 handleCurrentStepSave 的代码调用返回的是 [error, res] 的格式
onSaveAndNext = async () => {
this.handleCurrentStepSave()
.then((res) => {
if (Array.isArray(res) && res[0]) {
return;
}
const nextStep = this.ruleConfigStepList[this.state.currentRuleConfigStepIndex].nextStep;
if (nextStep) {
this.setState({
currentRuleConfigStepIndex: this.ruleConfigStep[nextStep].index,
});
} else {
// 最后一步没有 nextStep
this.props.dispatch({
type: 'routerJumpModal/setIsSaved',
payload: true,
});
}
})
.catch((err) => {
console.log('handleCurrentStepSave: ', err);
// Sentry.captureException(err);
});
};
// 改进
onSaveAndNext = () => {
this.handleCurrentStepSave()
.then(() => {
const nextStep = this.ruleConfigStepList[this.state.currentRuleConfigStepIndex].nextStep;
if (nextStep) {
this.setState({
currentRuleConfigStepIndex: this.ruleConfigStep[nextStep].index,
});
} else {
// 最后一步没有 nextStep
this.props.dispatch({
type: 'routerJumpModal/setIsSaved',
payload: true,
});
}
})
.catch((err) => {
// 如果 err 是数组表示表单校验未通过
if (isArray(err)) {
return;
}
Sentry.captureException(err);
});
};