MunMunMiao
MunMunMiao
请参考这个例子的最佳实践:https://github.com/NG-ZORRO/ng-zorro-antd/issues/7827#issuecomment-1640833742 NzComponentParams已在15.1.0标记为已弃用,16.0.0和16.1.0区别不大,可在16.0.0将modal改造好了再升级16.1.0
> 一些参考: ComponentInputBinding:https://angular.io/api/router/withComponentInputBinding ngComponentOutletInputs:https://angular.io/api/common/NgComponentOutlet 首先确认的一点是,即使有了``withComponentInputBinding``、``NgComponentOutlet``和``setInput``,对于modal类型的组件,也是不适用的。 因为这两个方法本质是对``Component``进行数据赋值操作,但是在需要open的modal时,最佳实践是使用官方CDK的[Overlay](https://material.angular.io/cdk/overlay/overview)为基础开发的各种modal,dialog,而非是``new ComponentI()``以及在template中使用,所以需要将modal所需的数据,在父组件中传递给需要modal的组件。 上述两个API是在``Component``创建时,将值传递给``Component``的Key上,在创建后不建议也不要去直接修改``Component``的值,因为``Component``不能感知到值的变化,从而会导致一些莫名其妙的问题,以及导致增加开发人员的心智负担,当然你可以使用各种方法去解决检测值的问题,但这不是这里需要解决的问题。类似的场景是官方的[CdkTable](https://material.angular.io/cdk/table/overview),如果``dataSource``传递的是一个``Array``而非``Observable ``或者``Promise``,你是需要再改变``Array``后,手动调用``renderRows`` ``ComponentRef``中的``setInput``可以解决父组件对已创建的子组件进行变更检测的问题,但是对于``Overlay``的场景不适用,因为在打开了``Overlay``之后,基本上不建议对其组件进行任何操作(这里指的是``Overlay``创建的组件,而非``OverlayRef``,动态调整``Overlay``窗口大小、位置是``OverlayRef``的范畴),多个组件需要同一个数据源的话,建议是使用``Service``,``provide``到“父组件”即可,无需``provide``到``root`` 现在回到主题,再来说说为什么不将modal data赋值到``Component``中 > 1.很重要的一点就是类型问题 因为现在ng使用的是装饰器将``Component``的key标记为可Input的key,但是ts没办法区分哪个值“被装饰”了,所以modal在data提供的``keyof Component``,实际上是不安全的,因为你可能会无意间设置了其他非``Input``的属性。 在未来的信号组件中,也许这个问题可以消失,因为信号的类型是``InputSignal``,可以过滤出来可以``Input``的值 但我觉得``NzComponentParams``基本不会复原,原因是即使信号组件推出了,那么原本的组件也是处于一个并行时期的,从大局上看,为了照顾到所有类型的组件以及API DX与官方保持一致的角度上看,放弃这种方式是没问题的。 我听说以后可能会有``Fcuntion Component``,到那时,这个问题将不是问题 : ),也许也变成类React了也说不定 > 2.无法在``constructor``使用 因为``Input``的值是需要等到``ngOnInit``后,才会被赋值,这会导致几个问题: 需要强制``id!: number``值的类型,如果没传值,或者没在正确的生命周期里使用,会使在使用过程中不容易发现这里实际上是可能为``undefined``即``id?: number``。如果标记了``undefined``,这样使用会在后续业务编写过程中,不断需要去写判断这个值是否为``undefined``,如果麻烦了,你还会强制断言,导致ts的优势在写业务过程中全无。举个例子: ```ts...
@nankingcigar 感谢你的回复。 我想先回答你的提出的一些观点 > Angular官方关于最佳实践的宣传可能要求较高的开发经验,而实际情况中,不是所有小型团队都能严格遵循这些最佳实践。很多人更希望能够快速上手,迅速进行开发和部署。 这点实际上是不存在的,因为难以上手的是Angular,而非相关组件库。 官方CDK是一个Angular使用的最佳实践,它与Angular同步更新,所以我建议ng-zorro能够与CDK的DX保持高度一致,其次再是拓展,这样可以保证Angular的用户体验从官方到第三方都能保持高度一致 > 使用nzComponentParams使组件不必关心参数的传递方式,无论是通过输入属性还是弹窗展示,开发者只需关注组件内部的业务逻辑。 如果真的需要``nzComponentParams``方便和其他地方复用,其实``nz-modal``支持以组件的方式进行打开的 ``ts `` > 我认为新版本中的信号组件用起来效果有限,适用场景有限,理解难度较大,组件内使用体验不佳 信号是Angular未来的响应式解决方案,所以信号是未来nz-zorro考虑的一个因素 > 大部分情况下,我这种小团队更多地使用ngOnInit而不是构造函数进行初始化 > 对于大部分非弹窗组件,输入属性通常在ngOnInit中进行初始化,这也是许多小型团队的实践 目前Angular作为使用Class为组件的框架,``constructor ``是不可忽视的一个点,``constructor ``用于在Class初始化前,对Class内部的参数进行设置 > 我赞同在输入属性声明中使用id!: number而不是id?: number,并且在实际项目中也采用了这种做法,避免了你提到的参数书写判断的情况。 > 对于可能为undefined的情况,我认为大部分小型团队都有测试人员或开发者自己编写简单的单元测试,因此解决undefined初始化问题的成本相对较低。 这样的做法实际上是“掩耳盗铃”,并不是报错不存在这种可能性,并且这会令重构造成一定程度的困难也失去了使用ts的优势。 在modal,drawer等需要服务打开的组件中,可以传递静态的``data``用来初始化modal所打开的组件,在该组件内的``constructor...
@HyperLife1119 是的,这些问题没有一个最优解,也是各种骚操作,唯一能做的只能是做好类型编写。 ``withComponentInputBinding``事实上我做过反对,但没卵用hhhhhh,当时还没有信号这个东西 https://github.com/angular/angular/pull/49633#issuecomment-1498209921 ``ComponentRef``的``setInput``是一个ok的做法,它的效果和``Input``是一样的,但这不是问题,问题是在open中,ts无法提供可Input的值,我也知道很繁琐每次都要写``open(C)``,可目前来说,保证完善类型的情况下,最佳的写法就是这样了要是有办法可以直接``open(C)``我就能知道需要Input啥,Output啥,那肯定最好不过了。 以我为例,我经历过“掩耳盗铃”的ts项目,也有严格完善类型的项目,后者对于开发人员日后维护、重构都起到了良好的作用,前者的话仁者见仁吧,但难看确实难看。 关于``constructor``,我想说,在class组件中还是很有必要考虑的,这毕竟是class本身的设计,除非将来使用了``Function Component``,但你想``Function Component``中的``Function``,不就是``constructor`` :),目前我全部使用了``inject``,基本上很少使用``constructor``了,但不能因为这样,而放弃了``constructor``的使用,因为在一些时候,它是很有用的。 目前我是很期待``InputSignal``的,我现在的项目全是以Signal实现了,就等着11月转为纯信号。
那要等明年了,哎,要是Function Component的话,那事情解决就容易多了
https://twitter.com/Jean__Meche/status/1718244500189954301 有开发者也是在constructor使用Input的值造成问题,这问题根本是class导致的,所以我希望设计组件的时候应该考虑constructor的使用场景 当然这个问题在以后的function component将不复存在
> I can help with standalone components. Someone already takes this or no? Welcome to participate
Please help repair the node version