很久没写相关的文章,正好前两天把抄来的Select组件重写了一下,简化了一些逻辑。
先看下zorro 中select组件的一个目录结构
zorro将select组件分成了 三大块
- Input / 选择框
- 下拉列表
- 连接以上2层的控制器层
先看 我们使用的 nz-select 内部的模板到底是什么样的
正如我们之前提到的那样, 整个组件结构分成三个部分 nz-select-top-control ,nz-option-container,以及该组件自身的 cdk-overlay
而我们的API用法则是
<nz-select>
<nz-option>
</...>
API语法更接近于原生的html体验。
实际上<nz-select>并不直接渲染 <ng-content>而是通过选择器
放入变量,传递到 nz-select-top-control ,nz-option-container,进行dom结构的渲染
三层的数据的走向都是相互的。即我变了传给你,你变了传给我。因此数据的传递主要依靠@input 去做数据的传递
整个代码实现逻辑也相对来讲比较复杂,或者说可以有点啰嗦,但是存在一些不得不解决的问题。比如说设置是否打开下拉框这一状态
由于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在select未打开的情况下,由于zorro的设置,overlay处于创建好的状态。除非nz-select组件被destroy掉。因此。页面select组件的多少。很大程度上影响了整个系统的性能。
”借鉴“nz-select的思路+ rxjs ,我们可以充分的自己改造/提升一下nz-select组件,将对组件的数据/状态操作抽离到 该select scope的service中去。
我把大部分状态的操作都通过BehaviorSubject 做媒介传递,(此处不能使用Subject,如需使用,也许会需要shareReplay
。
截取部分改变状态的代码。
当然,这里有一个注意点。由于overlay 中的option-container 超脱于三界之外。因此对于service 的scope注入不进去(非同一实例,因此,我们需要手动传值)
本篇结束,另祝广大Angular devs 元旦快乐。