「时光不负,创作不停,本文正在参加2021 年终总结征文大赛」
2020年11月离开待了5年的广州,来到深圳的现在的公司,当时前端团队有15人左右,但没想到的是,到了2021年的三月份已经走了9个老同事,其中有我的导师还有前端主管。特别是在主管走的那天,心情有点低落,因为团队的天花板很大部分在Leader。当时就在想跳槽就是为了找个厉害的leader、厉害的团队学到多点技术,但没想到现实却是这样。。。但啪的一下,很快啊,到了晚上下班我就调整了心态,既然天花板走了,那就自己努力提高团队的技术天花板吧。
这个是当天跟朋友的聊天,当时在工位还有点迷茫,等到走到楼下就迅速调整好心态了,用发展的眼光看问题真的是yyds
技术方面
源码
- React 源码。这是我从去年年末就跟前同事夸下的海口,说打算到2021的6月熟悉React源码,可是刚开始看就觉得源码太多太难,就搁置了。等到六月份再重新拿起来看,用了快两个月时间,一行行 debugger,到现在算是看了七八遍了,也算是对React源码比较熟悉,可见react-source-study
- redux、react-redux 源码。redux 之前主要是看各种源码解析的文章,可谓百行源码,万行思想,且里面用到了挺多设计模式的。在看完 React 源码之后,我就花了一周把 redux 和 react-redux 源码看完了,redux 本身不难,react-redux 可能要花点时间去消化理解。且最新的 redux 等都用 ts 重写,这个表示好评,而且也用了React18的
use-sync-external-store
,源码里面也有对这个进行解析。可见 redux、react-redux及相关中间件源码分析
- axios。axios 是我们一直用来请求数据的库,所以还是对它里面的实现比较感兴趣的,大概花了三四天看完,相对比较简单,但要吐槽的一点是 axios 没用 ts 写,强迫症的我用 ts 重写了。可见axios源码分析
- react-router、react-router-dom、history。是最新的 V6 版本,也是用 ts 重写了,之前写了个 专栏 ,有兴趣的可以看看。同时我也有幸成为了 react-router 的 contributor,可见 react-router、react-router-dom、history 源码分析
技术栈
今年主要掌握了如下技术栈:
- TS,现在能很熟练地使用
- mobx,上家公司是用 dva,所以今年才接触 mobx,前者是声明式,后者是响应式,跟 react 和 vue 挺类似
- react-native,从零到上线项目,也踩了很多坑,总结输出了一篇文章,不过由于涉及到业务相关,只发到公司语雀的内部
- taro 小程序,也是从零到上线项目,其中涉及到蓝牙打印的也踩了很多坑
- electron,主要是因为浏览器无法实现自动打印,所以通过electron实现下单后自动打印的功能
- 其他如 webpack5、vite 和 babel。webpack年初读了
tapable
(高级版的EventEmitter
,webpack底层的基础)、最近看的loader-runner
,还有一些基本配置;vite
现在都用于个人的项目,没有特别深入了解过,看什么时候公司的项目能平稳切换到vite
;babel
只学了一部分,接触了一点点AST
,学的不全面,这几个就一笔带过吧~
组件库
公司的 组件库主要由我来维护,不过,我接手的时候组件库其实是很不好用,比如:
- 之前的 Table 组件,要添加选择、subTable、固定列等功能都需要添加各种 HOC
- Form 表单功能单一,每个 FormItem 里面还得写 value和 onChange
- 很多组件如果不写props 如 value、data 就会报错,或者缺少泛型提示等等
sass
中后台 Table 和 Form 表单占据了绝大部分,这无疑给同事带来了很大的麻烦,为了减少同事的开发难度,我对组件库很多地方都做了改造。下面会以 Table 和 Form 作为例子,讲下我是如何改造组件库的。
1.改造Table
刚到公司的时候问同事如何使用,同事也不太清楚HOC的顺序,导致即使是老同事也可能不太清楚如何配置,那么要渲染一个Table,只能取CV以前其他同事的代码,但实际上是不知其所以然的。
这是刚到公司问同事 Table 的 HOC 如何配置
上面提到的问题我肯定是无法容忍的,就在某天,我突然想起下面代码中嵌套的各种 HOC 好像在哪里看过?
const KeyboardVirtualTable = diyTableHoc(
keyboardTableHoc(fixColumnsTableHoc(editTableHoc(TableVitualized)))
)
// 可不可以转换为下面这样?
const KeyboardVirtualTable = applyMiddleware([
diyTableHoc,
keyboardTableHoc,
fixColumnsTableHoc,
editTableHoc
])(TableVitualized)
啊!上面代码的各种HOC不就类似中间件吗!!
要让我记各种HOC是不可能的,这辈子都不可能的,所以就在某个周末,我把上面的想法实现了:
// util.ts
// 洋葱模型
const compose = (...fns: HocMiddleware[]): HocMiddleware => {
fns = [...fns]
if (fns.length === 0) {
return (node: ReactNode) => node
}
return fns.reduce((res, cur) => (...args: any) => res(cur(...args)))
}
// 中间件
const applyMiddleware = (...middlewares: HocMiddleware[]) => (node: ReactNode) => {
return compose(...middlewares)(node)
}
export { applyMiddleware }
上面参考了redux
实现了 compose
和 applyMiddleware
,然后通过各种 isXXX
prop来配置 Table 的功能:
function Table<D extends object = any>({
isDiy,
isBatchSelect,
isExpand,
isSort,
isEdit,
isSub,
isKeyboard,
isSelect,
isIndex,
...res
}: TableProps<D>) {
const Table = useMemo(() => {
// 按需引入
let keyboardTableXHOC
if (isKeyboard) {
keyboardTableXHOC = require('@gm-pc/keyboard').keyboardTableXHOC
}
// 配置中间件
const hocMiddles = [
isExpand && expandTableXHOC,
isBatchSelect && batchActionSelectTableXHOC,
isSelect && selectTableXHOC,
isIndex && indexTableXHOC,
isDiy && diyTableXHOC,
isSort && sortableTableXHOC,
isEdit && editTableXHOC,
isSub && subTableXHOC,
isKeyboard && keyboardTableXHOC,
].filter(Boolean) as HocMiddleware[]
const TempTable = applyMiddleware(...hocMiddles)(BaseTable)
return TempTable as typeof BaseTable
}, [
isDiy,
isBatchSelect,
isExpand,
isSort,
isEdit,
isSub,
isKeyboard,
isSelect,
isIndex,
])
const tableProps = (res as unknown) as TableProps<D>
return <Table {...tableProps} />
}
好了,现在终于不用再去记各种HOC和其顺序了,实现完之后,按捺不住内心的激动,就把上面的成果跟团队的成员分享了:
当然,给Table还加了泛型、表头排序等等功能,具体可看 gm-pc 1.2.3重大更新之TableX
2.ControlledForm<K>(受控表单)
原先表单组件都得传对应的 value 和 onChange,无法实现如统一管理、表单项联动等功能,导致代码相当地冗余,对前端开发者相当不友好,因此亟待受控表单来解决这一问题。
这里要注意,上面所说的 受控表单
实际意思是让 Form 自动处理 value 和 onChange,而不是开发者自己手写,因为原先的 Form 已经被占用了,所以我就另外取了个组件名。功能是参照antd的,即通过一个在 Form
里面使用 Context
,然后:
- 通过在
ControlledForm
中的ControlledFormContext
上下文Provide
对应的表单值及修改表单值的方法(providerValues
)、然后在ControlledFormItem
中通过useContext
获取到上下文的值 ControlledFormItem
中的组件无需传 value 和 onChange,源码根据valuePropName?: 'value' | 'checked' | 'selected' | 'date'
,trigger?: string
(组件修改值的回调函数名,如 onChange)劫持组件,给组件加上对应的 value和 trigger 函数,通过React.cloneElement
克隆新的组件
function ControlledFormItem<T = any>(props: ControlFormItemProps<T>) {
const {
name = '',
...restProps
} = props
const {
...
} = useContext(ControlledFormContext)
const childProps = {
...children.props,
}
// 如果有提供name
if (name) {
// 拦截加上value
childProps[valuePropName] = values?.[name]
const triggers = new Set<string>([trigger])
if (!Array.isArray(children)) {
triggers.forEach((eventName) => {
childProps[eventName] = (args: any) => {
// 触发更新
if (onChange) {
const newValue = onChange(name, args)
if (onFieldChange && resetFields && getFieldsValue && setFieldsValue) {
onFieldChange(newValue, { resetFields, getFieldsValue, setFieldsValue })
}
}
}
})
}
}
...
return (
<FormItem {...restProps}>
{cloneElement(children, childProps)}
</FormItem>
)
}
现在就无需手动受控组件了,不用再写各种冗余的 vlaue 和 onChange
当然,上面说的列表和表单肯定少不了各种泛型的实现:
这里就不一一说明的,感兴趣的可以看下:gm-pc 1.2.3重大更新,gm-pc 1.3.3 表单验证
非技术方面
1.看完了毛选一到八卷
学到了用发展的眼光看问题;没有调查没有发言权;实践论、矛盾论;革命乐观主义精神;认识世界,改造世界等等。毛选确实是一部宝藏书,但第一遍只是从头到尾看完,打算今后的几十年都多看看,领悟其中的精髓。
2.看完了红楼梦
然后还花了一段时间去搜集红楼梦的一些资料,如背景、解读、每个人的评价等等。
3.重温了鲁迅的一些小说
如《呐喊》、《狂人日记》、《孔乙己》、《药》、《风波》、《故乡》、《阿Q正传》等等。
4.重温了挪威的森林小说和电影
《挪威的森林》是很喜欢的一部小说,是大二看的,今年重新回味,不过电影感觉拍的不怎样。
5.看完了100集中国通史
大概是从三月份看到十二月,每天早上会看一点,看完感觉古代每个朝代的兴亡都是那么的类似,而且其中的历史人物如果能活得够久,那其成功的概率也相对较大。
6.长征、解放战争三大战役、朝鲜战争
在B站和知乎找一些上面提到的历史资料,背景,人物等等。我一个前同事说“我身边的朋友就你一人会去研究这些战争”,哈哈。当然,我所了解的只是一些皮毛而已,只是对这些比较感兴趣罢了。
作为面试官
作为一个过来者,之前一直是作为面试者的角色,也感受过一些面试官的颐指气使,所以以前就在想,如果以后做面试官了,无论面试者怎样,都应本着相互尊重的态度,毕竟人家大老远跑来面试,不是来受委屈的。
面试过程中如果不会或答错,我也会指出为何错误(有时间的情况下),也让人家面完有所收获。最后面完,我都会跟对方说,感谢抽出时间来面试,毕竟浪费别人时间无异于谋财害命,每个人的时间都是挺宝贵的。这样对方也对我们公司比较有好感,毕竟面试官的态度怎样决定了被面试者对公司的第一印象。
以下是一些面试者的评价,看到还是挺开心的:
2022年的展望
- 继续深入工程化方面,做工具链,深入学习 babel, AST,研究下 vite 等
- React 搞的差不多了,明年希望研究下 Vue,目前只停留在会用的阶段
- 成为React、Vue的
contributor
- 学习技术需要结合业务,服务业务,希望更深入了解公司业务,这样开发才比较游刃有余
- 涉猎下three.js,还有node框架nest或者egg还是midway?
最后
2021认识了很多大佬,其中不少比我年轻,他们是那么的年轻、厉害还努力,和他们相比,我真是菜鸡一个。但我相信只要每天进步一点点,终究只是时间问题,希望有一天能成为像他们那样的人~
感谢大家看到这样,最后,通过《实践论》最后一段来结束本文:
通过实践而发现真理,又通过实践而证实真理和发展真理。从感性认识而能动地发展到理性认识,又从理性认识而能动地指导革命实践,改造主观世界和客观世界。实践、认识、再实践、再认识,这种形式,循环往复以至无穷,而实践和认识之每一循环的内容,都比较地进到了高一级的程度。这就是辩证唯物论的全部认识论,这就是辩证唯物论的知行统一观。
2022, 继续努力,加油!各位!!