Zhuzhuchenyan

Angular 一个有关编程风格的问题

  •  
  •   Zhuzhuchenyan · Mar 6, 2020 · 2586 views
    This topic created in 2259 days ago, the information mentioned may be changed or developed.

    最近组织组内程序员们向 Angular 迁移,有个编程风格的问题想咨询一下大家。

    鉴于 Angular 大力推行 Rxjs 库的函数式思想比较有趣,同时又由于大家对这个范式的想法不同,写组件的时候浮现出很多不同的写法,例如下面这个小 Demo

    一个简单组件有一个布尔值用来控制一个内容是否显示,两个按钮用来控制这个布尔值是真是假

    //component.ts
    ... //跳过类内其他的定义
    stat: bool = false;
    
    onActiveButtonClicked():void {
    	this.stat = true;
    }
    
    onDeActiveButtonClicked():void {
        this.stat = false
    }
    ... //跳过类内其他的定义
    
    //component.html
    <button (click)="onActiveButtonClicked()">Active</button>
    <button (click)="onDeActiveButtonClicked()">Deactive</button>
    <p *ngIf="stat">Active</p>
    

    以上代码是程序员 A 贡献的,这个程序员呢原来是做 iOS 客户端开发的,熟练掌握 MVC 设计模式,根据习惯写出了以上代码,完美运行(那是当然的)他坚持只使用 rxjs 处理数据,而不是这种一眼就能看出来的情况

    还有一种写法如下,

    //component.ts
    ...
    dispatchAction: Subject<boolean> = new Subject<boolean>();
    shouldActive :Observable<boolean> = this.dispatchAction.pipe(
        startWith(false)
    )
    ...
    //component.html
    <button (click)="dispatchAction.next(true)">Active</button>
    <button (click)="dispatchAction.next(false)">Deactive</button>
    
    <p *ngIf="shouldActive | async">Active</p>
    

    这段代码是由我们刻苦学习的实习生贡献的,熟练运用 rxjs 给 Angular 赋能

    就事论事的话,我们暂且不考虑复杂的业务会给“MVC 程序员”(当然了我们现在是 MVVM )带来多大的思想负担导致他变成“Massive View Controller 程序员”,也不考虑复杂的业务会让实习生写出

    combinelatest(blablabal).pipe(bla(), merge(bkaba.pipe(nbikad)),switchmap(blablabal => forkjoin(blablalala)))
    

    这种给 code review 带来无穷麻烦的代码,以上两种写法各位偏向于哪一种呢?

    一个动态 DEMO 放在 stackblitz 上

    https://stackblitz.com/edit/angular-kssmku?embed=1&file=src/app/app.component.html

    在此先谢谢大家

    朱朱

    22 replies    2020-03-07 21:11:04 +08:00
    noe132
        1
    noe132  
       Mar 6, 2020
    我的倾向是不要在模板里写 rxjs。模板的数据来源应该尽可能简单,这样后期维护会方便很多
    其他地方怎么简单怎么写
    Zhuzhuchenyan
        2
    Zhuzhuchenyan  
    OP
       Mar 6, 2020
    @noe132 其实我这里更多想问的是,对于这个 active 的状态,更倾向于用何种方式去管理。
    第一种方式人类更能读懂,但是更新状态的代码散落在两个函数里
    第二种方式用 rxjs 的话,更有一种数据在单向流动的感觉,状态的更新完全是由 Observer 的逻辑在托管
    rrfeng
        3
    rrfeng  
       Mar 6, 2020 via Android
    显然第一种啊。rxjs 用在该用的地方,第二种就是纯粹为了用 rxjs 而用......

    楼上说的模板里不要写代码也是一种规范吧。
    noe132
        4
    noe132  
       Mar 6, 2020
    这并不冲突。
    你只要把函数改成 handleSetState(active: boolean): unknown 就可以了
    模板里写 handleSetState(true)
    Zhuzhuchenyan
        5
    Zhuzhuchenyan  
    OP
       Mar 6, 2020
    @noe132 的确这样似乎不错,handlestate 的逻辑就可以藏在 component 里了
    Zhuzhuchenyan
        6
    Zhuzhuchenyan  
    OP
       Mar 6, 2020
    @rrfeng 个人能容忍的底线也就是调用.next 了,比这个更复杂的都会让他们去修改。
    catoncat
        7
    catoncat  
       Mar 6, 2020
    shouldActive = new BehaviorSubject<boolean>(false);
    不行吗?
    shakaraka
        8
    shakaraka  
    PRO
       Mar 6, 2020
    ```ts
    isShow: BehaviorSubject<boolean> = new BehaviorSubject<boolean>(false)
    setStatus(value: boolean): void{
    this.isShow.next(value)
    }
    ```
    ```html
    <button (click)="setStatus(true)">open</button>
    <button (click)="setStatus(false)">close</button>
    <div *ngIf="isShow | async"></div>
    ```
    shakaraka
        9
    shakaraka  
    PRO
       Mar 6, 2020
    两行东西搞完的写那么复杂作甚?
    shakaraka
        10
    shakaraka  
    PRO
       Mar 6, 2020
    不要为了用而用
    nannanziyu
        11
    nannanziyu  
       Mar 6, 2020   ❤️ 1
    @wunonglin
    ... 哪儿用得了这么多行, 纯 html 就能实现

    ```
    <ng-container *ngIf="true; let isShow">

    <button (click)="isShow=true">Active</button>
    <button (click)="isShow=false">Deactive</button>

    <p *ngIf="isShow">Active</p>
    </ng-container>
    ```
    Zhuzhuchenyan
        13
    Zhuzhuchenyan  
    OP
       Mar 6, 2020
    @crs0910 完全可以的,在写的时候因为是从一个比较复杂的东西上拿下来的,所以没有这么写
    Zhuzhuchenyan
        14
    Zhuzhuchenyan  
    OP
       Mar 6, 2020
    @wunonglin 嗯,简单的东西肯定要保持简单,这里问的只是在复杂情况下的一种抽象而已
    catoncat
        15
    catoncat  
       Mar 6, 2020
    @Zhuzhuchenyan #13 刚好看到隔壁在讨论这个 https://www.v2ex.com/t/650483
    我觉得跟你的问题本质是相同的。
    我觉得算上产品迭代,技术沉淀等因素,在某些时候某些场景看似“过度”的解决方案,长远来看收益是大过于成本的。
    yuuko
        16
    yuuko  
       Mar 6, 2020
    如果只是简单的控制隐藏显示,肯定是第一种了,这种情况还用第二种的是为了用 rxjs 而用 rxjs。但是如果这个隐藏显示还要触发其他流程,比如数据获取之类的则可以用第二种。
    Zhuzhuchenyan
        17
    Zhuzhuchenyan  
    OP
       Mar 6, 2020
    @yuuko 嗯的确,这个例子的确太简单了。现在基本也是只有复杂逻辑才交给 rxjs 去做。
    Zhuzhuchenyan
        18
    Zhuzhuchenyan  
    OP
       Mar 6, 2020
    @crs0910 嗯我们现在对新东西也是摸着石头过河,整体的团队指导规范根据项目迭代以变化了好几版了。现在我们只有对“预估非常复杂的组件”才会使用较为复杂的结构,其他的东西我们宁愿写的越简单越好。
    crysislinux
        19
    crysislinux  
       Mar 6, 2020 via Android
    我们用了四年 angular 了,从 angular2 还是 beta 就在用。rxjs 这东西除非正好符合典型应用,否则还是别用。我们老大就喜欢瞎用,写的又臭又长,一旦 bug 简直无法。
    crysislinux
        20
    crysislinux  
       Mar 6, 2020 via Android
    而且 rxjs 这东西用多了,模板里到处 async,很难搞清楚到底哪个地方 trigger 了 change detection
    Zhuzhuchenyan
        21
    Zhuzhuchenyan  
    OP
       Mar 7, 2020
    @crysislinux 好的受教了,看来还是需要辨识出 rxjs 的典型场景。
    coloz
        22
    coloz  
       Mar 7, 2020
    状态管理 BehaviorSubject
    About   ·   Help   ·   Advertise   ·   Blog   ·   API   ·   FAQ   ·   Solana   ·   5530 Online   Highest 6679   ·     Select Language
    创意工作者们的社区
    World is powered by solitude
    VERSION: 3.9.8.5 · 50ms · UTC 07:43 · PVG 15:43 · LAX 00:43 · JFK 03:43
    ♥ Do have faith in what you're doing.