[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() ) } }
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· SQL Server 2025 AI相关能力初探
· Linux系列:如何用 C#调用 C方法造成内存泄露
· AI与.NET技术实操系列(二):开始使用ML.NET
· 记一次.NET内存居高不下排查解决与启示
· 探究高空视频全景AR技术的实现原理
· 阿里最新开源QwQ-32B,效果媲美deepseek-r1满血版,部署成本又又又降低了!
· Manus重磅发布:全球首款通用AI代理技术深度解析与实战指南
· 开源Multi-agent AI智能体框架aevatar.ai,欢迎大家贡献代码
· 被坑几百块钱后,我竟然真的恢复了删除的微信聊天记录!
· AI技术革命,工作效率10个最佳AI工具
2016-06-03 [Redux] Supplying the Initial State
2015-06-03 [D3] 6. Color Scale
2015-06-03 [D3] 5 .rangeBands
2015-06-03 [D3] 4. d3.max
2015-06-03 [D3] 3. Scaling Basics
2015-06-03 [D3] 2. Basics of SVG
2013-06-03 【PHP 】 伪静态 - 2. 使用apahce的rewrite机制(1) 开启rewrite模块,配置虚拟主机,对目录访问权限的修改