zoukankan      html  css  js  c++  java
  • [RxJS] RxJS Advanced Patterns Operate Heavily Dynamic UIs

     Check the playground.

    import {Counter, CountDownState, ConterStateKeys, PartialCountDownState} from './counter'
    import { Subject, Observable, merge, timer, NEVER, combineLatest} from 'rxjs'; 
    import { map, mapTo, switchMap, pluck, scan, startWith,shareReplay, distinctUntilChanged, withLatestFrom, tap} from 'rxjs/operators';
    
    // EXERCISE DESCRIPTION ==============================
    
    /**
     * Use `ConterStateKeys` for property names.
     * Explort the counterUI API by typing `counterUI.` somewhere. ;)
     * 
     * Implement all features of the counter: 
     * 1. Start, pause the counter. Then restart the counter with 0 (+)  
     * 2. Start it again from paused number (++) 
     * 3. If Set to button is clicked set counter value to input value while counting (+++)
     * 4. Reset to initial state if reset button is clicked (+)
     * 5. If count up button is clicked count up, if count down button is clicked count down  (+)
     * 6. Change interval if input tickSpeed input changes (++)
     * 7. Change count up if input countDiff changes (++)
     * 8. Take care of rendering execution and other performance optimisations as well as refactoring (+)
     */
    
    // ==================================================================
    
    // = BASE OBSERVABLES  ====================================================
    // == SOURCE OBSERVABLES ==================================================
    const initialConterState: CountDownState = {
      isTicking: false, 
      count: 0, 
      countUp: true, 
      tickSpeed: 200, 
      countDiff:1
    };
    
    const counterUI = new Counter(
      document.body,
      {
        initialSetTo: initialConterState.count + 10,
        initialTickSpeed: initialConterState.tickSpeed,
        initialCountDiff: initialConterState.countDiff,
      }
    );
    
    // === STATE OBSERVABLES ==================================================
    const programmaticCommandSubject = new Subject<PartialCountDownState>();
    const counterCommands$ = merge(
      counterUI.btnStart$.pipe(mapTo({isTicking: true})), 
      counterUI.btnPause$.pipe(mapTo({isTicking: false})),
      counterUI.btnSetTo$.pipe(map(n => ({count: n}))),
      counterUI.btnUp$.pipe(mapTo({countUp: true})),
      counterUI.btnDown$.pipe(mapTo({countUp: false})),
      counterUI.btnReset$.pipe(mapTo({...initialConterState})),
      counterUI.inputTickSpeed$.pipe(map ( n => ({tickSpeed: n}))),
      counterUI.inputCountDiff$.pipe(map ( n => ({countDiff: n}))),
      programmaticCommandSubject.asObservable()
    );
    
    const counterState$ = counterCommands$
    .pipe(
      startWith(initialConterState),
      scan((state, command) => ({
        ...state,
        ...command
      })),
      shareReplay(1)
    );
    
    // === INTERACTION OBSERVABLES ============================================
    const count$ = counterState$.pipe(
      queryState('count')
    );
    
    const isTicking$ = counterState$.pipe(
      queryState('isTicking')
    );
    const intervalTick$ = isTicking$.pipe(
      switchMap(isTicking => isTicking ? timer(0, initialConterState.tickSpeed): NEVER)
    );
    // = SIDE EFFECTS =========================================================
    // == UI INPUTS ===========================================================
    const renderCountChange$ = count$
    .pipe(
      tap((n: number) => counterUI.renderCounterValue(n))
    );
    
    // == UI OUTPUTS ==========================================================
    const commandFromTick$ = intervalTick$
      .pipe(
         withLatestFrom(count$, (_, count) => count),
         tap((count: number) => programmaticCommandSubject.next({count: ++count}))
      );
    
    // == SUBSCRIPTION ========================================================
    
    merge(
      // Input side effect
      renderCountChange$,
      // Outputs side effect
      commandFromTick$
    )
    .subscribe();
    
    
    // == CREATION METHODS ====================================================
    function queryState (name) {
      return function (o$) {
        return o$.pipe(
          pluck(name),
          distinctUntilChanged()
        )
      }
    }
  • 相关阅读:
    爬虫(Xpath)——爬tieba.baidu.com
    爬虫(正则)——爬neihan8
    爬虫(cookie)——renren模拟登陆
    爬虫(ProxyHandler)——代理
    爬虫(GET)——handler处理器和自定义opener
    爬虫(AJEX)——豆瓣动态页面
    爬虫(POST)——有道翻译(有bug)
    一次跨域请求出现 OPTIONS 请求的问题及解决方法
    现代JS中的流程控制:详解Callbacks 、Promises 、Async/Await
    nodejs中的子进程,深入解析child_process模块和cluster模块
  • 原文地址:https://www.cnblogs.com/Answer1215/p/10961805.html
Copyright © 2011-2022 走看看