2.7 api 使用
2.7.1 误用路由跳转
翻车指数:★★★★说明:使用a标签或者window.location.href去进行路由跳转的情况。
现场
| 
|
危害
| 导致页面重新加载,丢失应用状态,也无法做动画和过渡
破坏了历史记录管理
降低了代码的可维护性,一旦想调整应用的路由模式会需要修改很多分散的跳转代码
|
建议
| 建议一直使用history api或者Link组件保持SPA的良好体验。
|
2.7.2 new Promise()与Promise.resolve() 接口未择优
翻车指数:★
现场
| 
|
区别
| return Promise.resolve();是Promise API提供的一种快捷方式,用于创建一个立即解决的Promise。通常用于以下场景:
当你需要将一个非异步操作转换成异步操作以保持API的一致性时。
当你需要在异步函数中早期返回一个立即解决的值时。
return new Promise((resolve) => { resolve(); });是手动创建一个新的Promise对象,并在Promise构造函数中调用resolve方法。通常用于以下场景:
当你需要将现有的非Promise风格的异步操作(比如使用回调的旧式异步API)封装成Promise风格时。
当你的异步逻辑比较复杂,不仅仅是立即解决,而是需要执行一些操作后再解决。
当你需要根据某些条件或逻辑来决定是解决还是拒绝(reject)Promise时。
|
建议
| 当你只需要一个立即解决的Promise,并没有复杂的异步逻辑时,应该使用Promise.resolve()。而当你需要处理更复杂的异步逻辑,或者需要在异步过程中根据条件解决或拒绝Promise时,应该使用new Promise()构造函数。
|
2.7.3 React.createElement与jsx接口未择优
翻车指数:★
现场
| 
|
区别
| JSX更接近HTML语法,更易于编写和理解。相比之下createElement作为函数参数较多时代码可读性较低,需要明确指定每个元素的类型、属性和子元素,而JSX则可以很自然地嵌套并表达这些结构。
|
建议
| 通常推荐使用JSX。除非一些特定场景下(不使用jsx的环境、动态创建元素)使用createElement
|
2.7.4 误用stopPropagation
翻车指数:★
现场
| 
|
区别
| stopPropagation是用来阻止整个dom事件传递过程中该节点之后的事件传递,随意使用可能会引发一些意外的bug,比如说我们经常会将点击dom任意节点关闭模态框此类的事件绑定到document,而误用了该方法则会使委托在document上的事件失效,导致点击stopPropagation的元素无法关闭模态框。
|
建议
| 确实需要向父元素隔离事件时才使用。
|
2.8 重复造轮子
翻车指数:★★★★★说明:“重复造轮子”通常指的是在已有通用解决方案存在的情况下,开发者还是选择创建自定义的实现,团队目前主要存在以下两种情况会
对现有轮子的不熟悉
主观上对现有轮子的不认可
现场
|

|
危害
| 浪费时间和资源,维护成本还巨大
自己造的轮子可能存在边界场景考虑不全、缺乏充分测试、、缺乏社区支持、文档缺失或不完善等问题
不符合行业标准或最佳实践,只是自己“玩的爽”了
|
建议
| 新老司机结对编程或评审是熟悉团队轮子的最快路径
不要私自去推翻团队的技术选型(规范),如果轮子有问题放到团队层面去讨论解决方案,现实跑下来大部分还是回到了对现有轮子不够了解的问题上
|
2.9 TS 类型定义问题
2.9.1 AnyScript风
翻车指数:★★★★★说明:指的是 any 类型在 TypeScript 中过度使用的情况,经常类型问题难以解决了就会使出 any 这个“万金油”。
现场
|

|
危害
| 类型系统弱化,失去了自动补全和智能提示,在没有享受TS带来的优点的同时还徒增了很多代码
|
建议
| 将老项目逐渐升级到TypeScript项目的过程中使用any无可避免(也需有计划地最终去掉any),但增量代码应该尽量减少any的使用。
|
2.9.2 as everywhere
翻车指数:★★★★说明:评审中发现 as 同样是很多时候同学们快速绕过类型检查的一种方式。
现场
| 
|
危害
| 实际上是将类型错误的问题给隐藏起来了,阻止了类型推断,然后代码风险却一直存在。
|
建议
| as 关键字用于类型断言,允许你告诉编译器你知道一个变量的类型比它能推断出来的更确切,如果你发现自己过于频繁地使用 as,那么这可能是你的类型设计有问题,或者你需要改进你的类型定义的信号。
|
2.9.3 可空? everywhere
翻车指数:★★★★
现场
| 
|
危害
| 这是大部分过度使用可选链的一个诱因
|
建议
| 随意的可空? 通常代表你没有掌控或足够了解你的代码,再次建议一定要经过思考和了解你定义的字段是否可能为空,否则一定不要使?修饰 。
|
2.10 异常处理
异常处理时常容易被前端所忽略。
2.10.1 异常被吞没
翻车指数:★★★★说明:常出现的情况是要么catch了异常什么都不做,或者迫于eslint的检查会写一个console.log(error),又或者只是看似恢复了(不正确的)用户界面却丢失了案发现场,不再上报异常。
现场
| 
|
危害
| 异常通常由我们没有考虑到的意外情况引起,从中能发现业务逻辑中不易发现的问题,一旦我们捕获了这些异常,顶层的错误监控也不能主动捕获到这些问题,程序也许没有崩溃但如果没有用户告知我们,我们就无法发现用户的哪些功能无法正常使用了。
|
建议
| 写catch代码块时一定要想清楚哪些地方会引发异常,最起码要做的两件事是:
ui降级
异常上报
|
2.10.2 忽略了接口异常时的loading处理
翻车指数:★★★★
现场
| 
|
危害
| 接口一旦失败,用户将卡在loading中无法恢复,系统可用性降低。
|
建议
| 自己管理loading状态时,一定要注意在finally代码块中重置loading,或者可以选择useRequest这类高度抽象的hook去管理请求。
|
2.10.3 使用then catch then
翻车指数:★
现场
| 
|
建议
| Promise链式调用中的catch,建议在错误处理完终止链
|
三、什么是好的习惯
先消除代码编辑器和相关工具插件给你的所有警告;
不要在同一个地方跌倒,代码问题同样如此,吸收评审者给到的意见来武装自己,总归受益人是自己;
代码需要打磨设计,设计可以不完美,但不能不去思考设计;
这里单单还想说下工程师的信仰,当下我们的工程师们更多都在学习着谈产品谈业务,甚至会出现不为工程质量长久计的“快速”实现当下业务目标的想法,而忘了我们还要保证好的代码、好的文档、好的系统设计的时候,那一定是工程师们的失职,是追求卓越信仰的缺失,将软件工程师基本素养丢之于脑后带来的必然是一个个腐化的系统。确实很多时候我们会把忙当成自己的心理安全线去解释我们这么做的原因,可是否也该想想当不忙的时候,我们的代码离卓越还有多远。
四、写在最后
几乎没有哪个实践能有比代码评审之于技术团队的工程师文化建设更有意义,它是形成团队统一代码风格最有效的方式,持续做评审持续去改善是每个技术团队应该执行下去的事情,共勉!