Upgrade to Pro — share decks privately, control downloads, hide ads and more …

[ 改訂版 ] Cycle.js - リアクティブ・プログラミングに特化した JS フレームワーク

wakamsha
April 25, 2017

[ 改訂版 ] Cycle.js - リアクティブ・プログラミングに特化した JS フレームワーク

[ 追記 ] Meguro.es x Gotanda.js #1 にて発表した際の資料です。Node学園 25時限目 での内容に一部誤りがあったので訂正しました。

------

Node学園 25時限目 ( 2017年4月24日 ) にて発表した際の資料です。
Cycle.js という JS フレームワークの概要と仕組みについて簡単にご紹介しています。

こちらのブログ記事にてより詳しく解説していますので、併せて御覧ください。
https://tech.recruit-mp.co.jp/front-end/post-11898/

wakamsha

April 25, 2017
Tweet

More Decks by wakamsha

Other Decks in Programming

Transcript

  1. $ZDMFKT ϦΞΫςΟϒɾϓϩάϥϛϯάʹಛԽͨ͠+4ϑϨʔϜϫʔΫ - A functional and reactive JavaScript framework for

    predictable code -  /BPLJ:"."%" !XBLBNTIB /PEFֶԂ࣌ݶ໨.FHVSPFTº(PUBOEBKT
  2. import {Observable} from 'rxjs'; import {div, label, input, hr, h1,

    VNode, makeDOMDriver} from '@cycle/dom'; import {run} from '@cycle/rxjs-run'; import {DOMSource} from '@cycle/dom/rxjs-typings'; type Sources = { DOM: DOMSource; } type Sinks = { DOM: Observable<VNode>; } /** * ΞϓϦέʔγϣϯ * @param sources * @returns {{DOM: Observable<VNode>}} */ function main(sources: Sources): Sinks { // ΩʔೖྗΠϕϯτΛऔಘ ( Intent ) const input$: Observable<Event> = sources.DOM.select('.field').events('input'); // ೖྗΠϕϯτ͔Βݱࡏͷঢ়ଶͳ͍͠஋Λऔಘ ( Model ) const name$: Observable<string> = Observable.from(input$) .map((ev: Event) => ev.target.value) .startWith(''); // ݱࡏͷঢ়ଶΛը໘ʹඳը ( View ) const vdom$: Observable<VNode> = name$.map(name => {
  3. /** * ΞϓϦέʔγϣϯ * @param sources * @returns {{DOM: Observable<VNode>}}

    */ function main(sources: Sources): Sinks { // ΩʔೖྗΠϕϯτΛऔಘ ( Intent ) const input$: Observable<Event> = sources.DOM.select('.field').events('input'); // ೖྗΠϕϯτ͔Βݱࡏͷঢ়ଶͳ͍͠஋Λऔಘ ( Model ) const name$: Observable<string> = Observable.from(input$) .map((ev: Event) => ev.target.value) .startWith(''); // ݱࡏͷঢ়ଶΛը໘ʹඳը ( View ) const vdom$: Observable<VNode> = name$.map(name => { return div('.well', [ div('.form-group', [ label('Name: '), input('.field.form-control', {attrs: {type: 'text'}}), ]), hr(), h1(`Hello ${name}`) ]); }); // ݁ՌΛυϥΠόʹग़ྗ͢Δ ( Sinks ) return { DOM: vdom$ }; }
  4. label('Name: '), input('.field.form-control', {attrs: {type: 'text'}}), ]), hr(), h1(`Hello ${name}`)

    ]); }); // ݁ՌΛυϥΠόʹग़ྗ͢Δ ( Sinks ) return { DOM: vdom$ }; } // ΞϓϦέʔγϣϯ͔Βͷ໭Γ஋Λड͚औΔυϥΠό܈Λఆٛ const drivers = { DOM: makeDOMDriver('#app-container') }; // ΞϓϦέʔγϣϯͱυϥΠόΛ݁ͼ͚ͭΔ run(main, drivers);
  5. label('Name: '), input('.field.form-control', {attrs: {type: 'text'}}), ]), hr(), h1(`Hello ${name}`)

    ]); }); // ݁ՌΛυϥΠόʹग़ྗ͢Δ ( Sinks ) return { DOM: vdom$ }; } // ΞϓϦέʔγϣϯ͔Βͷ໭Γ஋Λड͚औΔυϥΠό܈Λఆٛ const drivers = { DOM: makeDOMDriver('#app-container') }; // ΞϓϦέʔγϣϯͱυϥΠόΛ݁ͼ͚ͭΔ run(main, drivers);
  6. driver() main() ঢ়ଶ ( State ) ෭࡞༻ ( Effective )

    DOM API Source Stream %FTJHOQIJMPTPQIZPG$ZDMFKT
  7. driver() main() ঢ়ଶ ( State ) ෭࡞༻ ( Effective )

    DOM API Source Stream Sink Stream %FTJHOQIJMPTPQIZPG$ZDMFKT
  8. Rx.Observable .timer(0, 1000) .map(i => `Seconds elapsed: ${i}`) .subscribe( (text:

    string) => { const container = document.querySelector('#app'); container.textContent = text; } ); ঢ়ଶ ( State ) ෭࡞༻ ( Effective ) %FTJHOQIJMPTPQIZPG$ZDMFKT
  9. Rx.Observable .timer(0, 1000) .map(i => `Seconds elapsed: ${i}`) .subscribe( (text:

    string) => { const container = document.querySelector('#app'); container.textContent = text; } ); ঢ়ଶ ( State ) ෭࡞༻ ( Effective ) %FTJHOQIJMPTPQIZPG$ZDMFKT
  10. Rx.Observable .timer(0, 1000) .map(i => `Seconds elapsed: ${i}`) .subscribe( (text:

    string) => { const container = document.querySelector('#app'); container.textContent = text; } ); Observable Subject ঢ়ଶ ( State ) ෭࡞༻ ( Effective ) %FTJHOQIJMPTPQIZPG$ZDMFKT
  11. function main() { return Rx.Observable .timer(0, 1000) .map(i => `Seconds

    elapsed: ${i}`); } function DOMDriver(text$: Observable<string>) { text$.subscribe( (text: string) => { const container = document.querySelector('#app'); container.textContent = text; } ); } Observable Subject %FTJHOQIJMPTPQIZPG$ZDMFKT
  12. function main() { return Rx.Observable .timer(0, 1000) .map(i => `Seconds

    elapsed: ${i}`); } function DOMDriver(text$: Observable<string>) { text$.subscribe( (text: string) => { const container = document.querySelector('#app'); container.textContent = text; } ); } // Run const sink = main(); DOMDriver(sink);
  13. function main() { return Rx.Observable .timer(0, 1000) .map(i => `Seconds

    elapsed: ${i}`); } function DOMDriver(text$: Observable<string>) { text$.subscribe( (text: string) => { const container = document.querySelector('#app'); container.textContent = text; } ); } // Run const sink = main(); DOMDriver(sink); // υϥΠό܈Λఆٛ
 const drivers = {
 DOM: makeDOMDriver('#app')
 };
 // main ͱυϥΠόΛ݁ͼ͚ͭΔ
 run(main, drivers);