![968268a707b33b79c396153c0cff6a01.gif](https://i-blog.csdnimg.cn/blog_migrate/afa0a32fd145fd6a727baa36fb17666a.gif)
原文:
基于react+ts写了个级联选择器——react-cascader-transfer · Issue #45 · lizhongzhen11/lizz-bloggithub.com![c61cc3a1ace3bb8a89ea5769be6a7b0b.png](https://i-blog.csdnimg.cn/blog_migrate/3285fbb2e88d6f53954e900736259ddd.jpeg)
正文:
npm地址:react-cascader-transfer
github:lizhongzhen11/react-cascader-transfer
效果图:
![968268a707b33b79c396153c0cff6a01.gif](https://i-blog.csdnimg.cn/blog_migrate/afa0a32fd145fd6a727baa36fb17666a.gif)
开发背景
最近做的项目中涉及到地区选中以及项目及项目下的设备选择等需求。采用的是react + ts + antd开发。
antd很不错,提供了级联选择器,只是,它把级联放到下拉框里我不喜欢,而且只能单选,一开始有想把 cascader 和 transfer 结合下来解决我需要的,就像官方提供的 tree + transfer 那样,但是实际操作起来并不容易,最主要的是,我并不需要transfer,这个transfer 的效果不是我想要的。
想起来,上家公司工作时,产品经理抄头条广告后台管理系统的UI时,不仅抄了星期时间范围选择器,还抄了它的级联交互,不过那个是我同事写的,基于vue写的,具体代码是什么我也没仔细看过,依稀记得他说用了什么算法的,哎,时间紧当初没好好看,自己现在要用到类似的组件了,自己只能从头写了。
开发过程
完成 vue-week-time-range-picker 和 react-week-time-range-picker 后我就开始想要去开发这个 react-cascader-transfer 组件了。
嗯,当时是10月4号还是5号来着的,我上班了,然后,我搭了个环境,然后,神游太虚。
第二天,我画了个已选面板,调下样式,神游太虚。
第三天,我开始画级联面板,调调样式,神游太虚。
第四天,开始。
总的来说,还是有点复杂的,我代码写的也不算好,用到了不少递归。
首先这种级联吧,得确定多少层级,那么肯定是常见的 tree 结构,为了给组件用,肯定需要统一 tree 的格式,我看了下antd的
级联选择 Cascader - Ant Designant.design![5db5d99d0cd5de5669feaa13dc637980.png](https://i-blog.csdnimg.cn/blog_migrate/8ececee43b524400b4687dd22e5f67cb.png)
,嗯,就用它了,在它基础上扩展下就好了。
结构有了,要考虑如何展开子层?
初始化就去确定有多少层还是手动点击在确定展开的层级呢?
我选择第二种手动点开确定。初始化就展开没啥必要。
这就需要考虑展开的层级数据,仅仅靠之前的 tree 结构不足以完成,我因此扩展了 level 属性,确定层级。
同时,我还需要确定父子关系,仅靠 children 属性,子层无法得知谁是父层,因此我还要添加个 parentId 属性来确定。(PS:有的数据可能会提供该属性,有的话直接用就可以了,否则我会默认让父层的 value 成为子层的 parentId)
展开依赖于点击事件,这里就要注意到:可能子层已经展开过了,这个情况要避免。
这个完成后,神游太虚。
第五天,去了趟南京复查。
第六天,要加checkbox和checkbox选中状态改变了。
为了实现这个功能,需要加 checked 属性,顺带说一下,checkbox用的 antd 现成的,所以打包起来有点大。。。
checkbox选中状态改变,子孙层肯定会随着改变,但是父层不一定。子孙层的checkbox状态跟着当前checkbox改变层的状态而变化。
但是,需要考虑到以下两种情况:
1. 当前层取消选中,其父层原先选中,需要将其父层也取消选中;
2. 当前层选中,其兄弟层都已经选中,需要将父层也选中。
针对这两种情况,主要逻辑代码在 changeAncestorsChecked 方法中,会一直递归到顶层。
思考+编写测试一段时间,完成了。
然后就是具体的数据问题了,不管怎么点击,我都需要将数据实时拿到,会涉及到子层数据全选,合并成父层数据来替换,这些步骤花了不少时间,主要逻辑代码依然在 changeAncestorsChecked 和 handleSelected 方法中。
当然,由于判断太多,使用了策略模式优化了部分代码,也算学到的东西有了用武之地。
不过开发到下班时,还有bug。
今天第七天,早上奋力敲代码,总算完成初版,包括删除右侧已选中面板数据。
目前已发到npm上,地址:react-cascader-transfer
感想
写这些组件一是为了方便以后自己用,二是寻求点成就感。
如果我不写,
那么我不会知道如何发包到npm上;
我也不会去想着用webpack搭建简单的react或vue环境;
我更不会将之前所学的知识用于实践;
最终,碰到点复杂的东西,我可能都不愿意去动脑子思考;
久而久之,我可能就固步自封了。
但是我写了,有了新的尝试,新的收获。