Real World Virtual DOM

Real World Virtual DOM

React, Flux, Isormorphic そして現実

3aebd86547bfc5cdb451d5f2f95ed5d8?s=128

Koutarou Chikuba

February 16, 2015
Tweet

Transcript

  1. 4.

    Virtual DOM ʹ͍ͭͯͷ׆ಈ ☞ VirtualDOM Advent Calendar 2014 - Qiita

    ͷओ࠵ ☞ ͋ͳ͕ͨReactΛ࢖͏΂͖ཧ༝ ☞ ͳͥԾ૝DOMͱ͍͏֓೦͕ԶୡͷࠢΛ਒͑ͤ͞Δ ͷ͔ - Qiita ☞ #13 Virtual DOM | mozaic.fm ͷήετ
  2. 11.

    ࠓ೔ͷςʔϚ Real World Virtual DOM ☞ ୈҰষ: Kobito on AtomShell

    ☞ ୈೋষ: Arda - MetaFlux Framework ☞ ୈࡾষ: Isormorphicͷ࣮ફ ☞ ࠷ޙʹ: Virtual DOM ΛͱΓ·͘ݱ࣮
  3. 14.
  4. 19.
  5. 22.

    ։ൃաఔ ☞ اը / ϓϩτ 10݄ޙ൒ ~ ☞ ઃܭ -

    11݄ ~ ☞ ࣮૷ - 12݄~ ☞ όάચ͍ग़͠ͱϦϑΝΫλ(͍·͜͜) ΤϯδχΞ1ਓ(mizchi) 1݄͔ΒϚʔΫΞοϓ1ਓ
  6. 44.

    react-jade ͷྫ .container h1(onClick=onClickTitle)= This is title ↓ React.createElement('div', {className:

    'container'}, [ React.createElement('h1', {onClick: onClickTitle}, 'This is title') ]) // ϔομলུ ͍ΘΏΔhamlܥςϯϓϨʔτ
  7. 46.

    ։ൃݴޠ ☞ UI૚: React Component / Dispatcher ☞ CoffeeScriptͰߴ଎ʹTry &

    Error Λճ͢ ☞ ςϯϓϨʔτ͸react-jade ☞ Store૚ / Domain૚ ☞ TypeScript ͷ common.jsϞʔυ ☞ CoffeeScript ʹ require ͞ΕΔ(ٯ͸ͳ͍)
  8. 49.

    ཚཱ͢Δ Flux ࣮૷ ☞ Fluxxor ☞ Reflux ☞ Alt ☞

    Fluxible ☞ Facebook's flux ☞ Deloerean ☞ etc...
  9. 55.

    Arda ☞ mizchi/arda - Github ☞ ݩʑ͸ Kobito on Atom

    Shell ͷঢ়ଶ؅ཧͱը໘ભ ҠΛந৅Խͨ͠΋ͷ ☞ ͦͦ͜͜ςετॻ͍ͯɺ͍ͩͿυοάϑʔσΟϯ ά͍ͯ͠ΔͷͰ࣮༻ʹ଱͑͏Δ͸ͣ
  10. 60.
  11. 62.

    Context ͷσʔλϑϩʔ ➀ Router ͔Βॳظೖྗ(Props)Λड͚ͯॳظԽ͞ΕΔ ➁ Props͔ΒॳظState(Context಺ঢ়ଶ)Λ࡞Δ ➂ Props ͱ

    State ͔ΒɺComponentʹ౉͢ϓϩύς Ο(ComponentProps)Λੜ੒ ➃ Component ʹ౉͢ ➄ ঢ়ଶ͕ߋ৽͞ΕͨΒ3ʹ໭Δ
  12. 63.
  13. 64.

    Arda.Router ☞ pushContext ☞ popContext ☞ replaceContext ☞ APIͰ࡯ͯ͠ ☞

    Contextͷੜ੒ͱഁغΛ୲౰(SPA͸ͦ͜Β΁Μݫ͠ ͍)
  14. 65.

    ΫϦοΫͰ਺͕૿͑Δαϯϓϧ class Clicker extends Arda.Component render: -> React.createElement 'button', {onClick:

    @onClick.bind(@)}, @props.cnt onClick: -> @dispatch 'clicker:++' class ClickerContext extends Arda.Context @component: Clicker initState: (props) -> cnt: 0 expandComponentProps: (props, state) -> cnt: state.cnt delegate: (subscribe) -> super subscribe 'clicker:++', => @update((s) => cnt: s.cnt+1) router = new Arda.Router(Arda.DefaultLayout, document.body) router.pushContext(ClickerContext, {})
  15. 66.

    ΫϦοΫͰ਺͕૿͑Δαϯϓϧ class Clicker extends Arda.Component render: -> React.createElement 'button', {onClick:

    @onClick.bind(@)}, @props.cnt onClick: -> @dispatch 'clicker:++' #<= EventEmitter΁ൃՐ class ClickerContext extends Arda.Context @component: Clicker initState: (props) -> cnt: 0 expandComponentProps: (props, state) -> cnt: state.cnt delegate: (subscribe) -> super subscribe 'clicker:++', => #<= EventEmitterͷEventड৴ @update((s) => cnt: s.cnt+1) router = new Arda.Router(Arda.DefaultLayout, document.body) router.pushContext(ClickerContext, {}) Event ͸Ұํ௨ߦ
  16. 67.

    ΫϦοΫͰ਺͕૿͑Δαϯϓϧ class Clicker extends Arda.Component render: -> React.createElement 'button', {onClick:

    @onClick.bind(@)}, @props.cnt onClick: -> @dispatch 'clicker:++' class ClickerContext extends Arda.Context @component: Clicker initState: (props) -> cnt: 0 #<= ॳظঢ়ଶ expandComponentProps: (props, state) -> cnt: state.cnt #<= ComponentͷProps delegate: (subscribe) -> super subscribe 'clicker:++', => @update((s) => cnt: s.cnt+1) #<= ঢ়ଶͷߋ৽ router = new Arda.Router(Arda.DefaultLayout, document.body) router.pushContext(ClickerContext, {}) Mutable ͳͷ͸ State ͚ͩ
  17. 68.

    Context Λ TypeScript Ͱهड़͢Δ ͱԿ͕خ͍͠ʁ ☞ ܕʹΑͬͯ࢓༷͕໌֬ʹͳΔ ☞ Props ͸ը໘Λ࠶ߏங͢Δͷʹඞཁͳ৘ใ

    ☞ State ͸ͦͷը໘ͷதͰมԽ͢Δঢ়ଶ ☞ ComponentProps ͸ ࣮ࡍʹComponent ʹ౉͞Ε Δ΋ͷ
  18. 70.

    ͨͱ͑͹ ☞ Stateͱͯ͠Կ͔ͷ id ͚ͩ࣋ͬͯ DB΍ωοτϫʔ ΫΛୟ͘ͱɺ݁Ռʹ࠶ݱੑ͕ͳ͘ State ͱͯ࣋͠ ͪͨ͘ͳ͍

    buildTimelineByGroupId(state.selectedGroupId).then((items) = { this.render(items); // ͜͜Λ࣋ͪͨ͘ͳ͍ });
  19. 71.

    ࠶ݱՄೳͳϏϡʔ ☞ ComponentProps͕ಉ͡ͳΒඞͣಉ͡ϏϡʔΛঢ় ଶΛ࠶ݱͰ͖Δ(ͱ͢Δ) ☞ Component ͱ Props ͷ૊Έ߹Θͤͷ URL΁ͷγ

    ϦΞϥΠζ/σγϦΞϥΠζ Λ࣮૷͢Ε͹ Browser Hisotry ʹରԠՄೳ ☞ Agnosticʹ͍ͨ͠ͷͰArdaͰ͸ϒϥ΢βώετϦ ʔΛؔ஌͠ͳ͍
  20. 73.

    Kobito on Atom Shell Ͱͷ Arda ☞ Context Λ TypeScript

    ͰܕͰอޢ͢Δɻ ☞ Component ͸ CoffeeScript Ͱࡶʹॻ͍ͯ Event Λ dispatch ͢Δ ☞ Eventͷߪಡଆ͸TypeScript Ͱॻ͍͍ͯΔ͕ɺड ͚औΔҾ਺ʹ͍ͭͯ͸͓໿ଋఔ౓
  21. 74.

    Arda with TypeScript interface Props {firstName: string; lastName: string;} interface

    State {age: number;} interface ComponentProps {greeting: string;} class MyContext extends Arda.Context<Props, State, ComponentProps> { initState(props){ return new Promise<State>(done => { setTimeout(done({age:10}), 1000) }) } expandComponentProps(props, state) { return {greeting: 'Hello, '+props.firstName+', '+state.age+' years old'} } } # தུ router.pushContext(MyContext, {firstName: 'Jonh', lastName: 'Doe'})
  22. 80.

    Qiita ͱ Atom Shell ಛ༗ͷࣄ৘ ☞ node ͷ global ͱ

    ϒϥ΢βͷ window ͕ڞଘ͢Δ ಛघͳ؀ڥ ☞ ੒Ռ෺͸͍ͣΕQiita΁࣋ͪࠐΈ͍ͨ ͱ͍͏Θ͚ͰKobito on Atom Shell Ͱ͸ Isomorphic Λڧ͘ҙࣝͯ͠ઃܭͨ͠
  23. 86.
  24. 87.

    mochaͰͷ࣮ࡍͷίʔυͷҰ෦ schema.databases[0].type = 'memoryDb' global.stubDatabases = -> # helper beforeEach

    -> initDatabasesBySchema(schema).then ([db]) -> global.db = new Repository.Database(db) global.Item = db.getCollection('items') global.Team = db.getCollection('teams') afterEach -> delete global.db delete global.Item delete global.Team
  25. 90.

    renderToString(...) var Component = React.createClass({ render: function(){return React.createElement('div', {}, 'this

    is title');} }); var html = React.renderToString(React.createFactory(Component)()); assert.ok(html.indexOf('this is title') > -1); componentWillMount ·Ͱݺ͹ΕΔͷ͕ϙΠϯτ (componentDidMount͸ݺ͹Εͳ͍)
  26. 91.

    JSDOM jsdom = require('jsdom').jsdom; global.document = jsdom('<html><body></body></html>'); global.window = document.parentWindow;

    global.navigator = window.navigator; React = require('react/addons'); var el = React.createElement('div'); component = React.addons.TestUtils.renderIntoDocument(el) αʔόʔ(node)ͰΫϦοΫΠϕϯτൃՐ΋ςετͰ͖ Δɻ ࢀߟ: JSDOMͱReact.addons.TestUtilsͰReactΛϔου Ϩεʹςετ͢Δ - Qiita
  27. 93.

    Kobitoͷ Isomorphic ͷ࣮ફ ☞ src/(.ts, .jade, .coffee) Λ૬ରύεΛҡ࣋ͨ͠··ί ϯύΠϧ͠ lib/(**.js)΁

    ☞ browserifyͰ lib/index.js Λ શ෦ೖΓ (node_modulesҎԼͷґଘؚΉ)ͷ bundle.js ͱ͠ ͯϏϧυ (gulpͰ֦ுࢠ͝ͱʹ؂ࢹͯࠩ͠෼Ϗϧυ)
  28. 94.

    src/ - main.coffee - foo.ts - template.jade lib/ - main.js

    - foo.js - template.js public/ - bundle.js # lib node_modules ͷґଘશ෦ೖΓ - index.html node_modules/ - ... test/ - main-test.coffee
  29. 109.
  30. 118.

    ׬