![0f660406fcc63cc8ca128371e15e5e76.png](https://i-blog.csdnimg.cn/blog_migrate/5e0333a64b7363db80135fccb5261937.jpeg)
很久没写相关的文章,正好前两天把抄来的Select组件重写了一下,简化了一些逻辑。
先看下zorro 中select组件的一个目录结构
![a4f33e65d60ef27024c21b77c9f58d81.png](https://i-blog.csdnimg.cn/blog_migrate/bc3db36390698a4583616e8be196ad0a.jpeg)
zorro将select组件分成了 三大块
- Input / 选择框
- 下拉列表
- 连接以上2层的控制器层
先看 我们使用的 nz-select 内部的模板到底是什么样的
![d36affc5359653b707e7bc0193c918bd.png](https://i-blog.csdnimg.cn/blog_migrate/5a7f5ec3bdd058e98fd0e2b0624f5d81.jpeg)
正如我们之前提到的那样, 整个组件结构分成三个部分 nz-select-top-control ,nz-option-container,以及该组件自身的 cdk-overlay
而我们的API用法则是
<nz-select>
<nz-option>
</...>
API语法更接近于原生的html体验。
实际上<nz-select>并不直接渲染 <ng-content>而是通过选择器
![68102dc3353cb9e894f723c7f4f165fe.png](https://i-blog.csdnimg.cn/blog_migrate/78ef77e2ab9c9870658ed3b4de7e2a8e.png)
放入变量,传递到 nz-select-top-control ,nz-option-container,进行dom结构的渲染
三层的数据的走向都是相互的。即我变了传给你,你变了传给我。因此数据的传递主要依靠@input 去做数据的传递
![b7d811834acb5e6adf32791982d308de.png](https://i-blog.csdnimg.cn/blog_migrate/7a4b42d5e9c1419e20c7f025b8ee872f.jpeg)
整个代码实现逻辑也相对来讲比较复杂,或者说可以有点啰嗦,但是存在一些不得不解决的问题。比如说设置是否打开下拉框这一状态
![674ffdcc6d9769543ef0987d2d75b7c4.png](https://i-blog.csdnimg.cn/blog_migrate/bafead89919ea7ed085db2d7171d9033.jpeg)
由于API本身比较丰富,功能强大,因此要考虑的部分也比较多
这里主要考虑了几个问题
- 在搜索模式下input的选中问题
- 滚动问题
- overlay打开的时候的层级覆盖问题,(由于overlay在dom中越前面层级越下,因此select可能会和其他同样使用overlay打开的组件层级互相覆盖)此处需把select指定。
- top-control和option-container的一些状态设置问题
由于把nz-select本身做数据处理媒介,再加上组件API功能强大,因此组件看上去比较臃肿。
当然,整个select组件在性能上也有些许问题,如该issue描述
Please consider removing cdkConnectedOverlay element when `nz-select`s are not open, like what `nz-dropdown` does · Issue #2465 · NG-ZORRO/ng-zorro-antdgithub.com![acf9c29edf075105879699729ade61e2.png](https://i-blog.csdnimg.cn/blog_migrate/f7b624dc5c5d6db2a19b9ca901bdcaba.jpeg)
在select未打开的情况下,由于zorro的设置,overlay处于创建好的状态。除非nz-select组件被destroy掉。因此。页面select组件的多少。很大程度上影响了整个系统的性能。
”借鉴“nz-select的思路+ rxjs ,我们可以充分的自己改造/提升一下nz-select组件,将对组件的数据/状态操作抽离到 该select scope的service中去。
![b132123e3f9029eea0ce81599f5c3fe7.png](https://i-blog.csdnimg.cn/blog_migrate/55ca6f29c63d8340202b542250694c37.jpeg)
![2c2c9987d9efa9221b491461772b2b4e.png](https://i-blog.csdnimg.cn/blog_migrate/ad4a4d23b2ed9a8db82f1878b7cc8066.jpeg)
我把大部分状态的操作都通过BehaviorSubject 做媒介传递,(此处不能使用Subject,如需使用,也许会需要shareReplay
。
![32d7cbadae7abda27c3ea8d7e89f1ff9.png](https://i-blog.csdnimg.cn/blog_migrate/7f3c20b14d03f015e2548c01ae7471e2.jpeg)
截取部分改变状态的代码。
当然,这里有一个注意点。由于overlay 中的option-container 超脱于三界之外。因此对于service 的scope注入不进去(非同一实例,因此,我们需要手动传值)
![f39d5b773a3d93acb75322ef696b4e8c.png](https://i-blog.csdnimg.cn/blog_migrate/a1dfb64c320f59e74afa6ec6c6edad3b.jpeg)
本篇结束,另祝广大Angular devs 元旦快乐。