Slide 1

Slide 1 text

ϑϩϯτΤϯυ΋,PUMJOͰॻ͖͍ͨʂ 8FCϖʔδΛ,PUJO+4Ͱ࡞ͬͨي੻ ,PUMJO'FTU ʹ͜͠Γ͞ͿΖʙ!TVCSPI@

Slide 2

Slide 2 text

"CPVU.F w ʹ͜͠Γ͞ͿΖʙ ຊ໊ࡔ্੖৴ w ౦ژ౎ɾҏ౾େౡग़਎ w גࣜձࣾ#FBS5BJM w "OESPJEΤϯδχΞ ,PUMJO+BWB ˑ w 8FCΤϯδχΞ 3BJMT3FBDU w झຯͰ,PUMJO+4

Slide 3

Slide 3 text

"HFOEB ,PUMJO+4ͷ֓ཁ w ྺ࢙ɺࣄྫ঺հCZTVCSPI@ ,PUMJO+43FBDUKTͰʮ)FMMP 8PSMEʯ w OQN,PUMJO+4 w (SBEMF,PUMJO+4 ,PUMJO+4ΞϓϦ΁ͷ+4੡ϥΠϒϥϦͷಋೖ

Slide 4

Slide 4 text

͜ͷηογϣϯΛ௨ͯ͠ʜ w ,PUMJO+4Λ࢖ͬͯ؆୯ͳ8FCΞϓϦΛ࡞Δ͜ͱ͕Ͱ͖Δ w ,PUMJO+4Ͱͷ։ൃͷΠϝʔδڞ༗ w ,PUMJO+4ΞϓϦ΁ͷ+4੡ϥΠϒϥϦಋೖͷ஌ݟڞ༗ w +4੡ϥΠϒϥϦΛ,PUMJOΒ͘͠ѻ͏ͨΊͷ5JQTɺϋϚΓͲ͜Ζղઆ

Slide 5

Slide 5 text

,PUMJO+4ͷ֓ཁ

Slide 6

Slide 6 text

rެࣜϦϑΝϨϯεݪจ l,PUMJOQSPWJEFTUIFBCJMJUZUPUBSHFU+BWB4DSJQU*UEPFTTPCZ USBOTQJMJOH,PUMJOUP+BWB4DSJQUz ,PUMJO+4ͷ֓ཁ ,PUMJO+4ͱ͸ʜ ,PUMJOΛ+4ͷίʔυ΁τϥϯεύΠϧ͢Δػೳɺ͓ΑͼϑϨʔϜϫʔΫ܈

Slide 7

Slide 7 text

,PUMJO+4ͷ֓ཁ +4ͰͷϑϩϯτΤϯυ։ൃʹඞཁͳϞϊ w +4ίʔυɾελΠϧγʔτ $44 ɾ)5.-ϑΝΠϧ w ύοέʔδ؅ཧπʔϧ OQN w Ϟδϡʔϧόϯυϥʔ 8FCQBDL w ෳ਺ͷ+4ϞδϡʔϧΛͭʹ·ͱΊɺ)5.-Ͱѻ͍΍͍͢ܗʹ͢Δ w Ϟδϡʔϧؒͷґଘؔ܎ղܾɺNJOJGZɺίʔυɾϦιʔεͷม׵ ྫ54ˠ+4ɺ4BTTˠ$44

Slide 8

Slide 8 text

,PUMJO+4ͷ֓ཁ w +4ίʔυʹม׵Մೳͳ,PUMJOඪ४ϥΠϒϥϦ w ,PUMJOˠ+4΁ͷม׵Λ࣮ߦ͢Δ(SBEMFϓϥάΠϯ w OQN8FCQBDLͷίϚϯυΛ࣮ߦ͢Δ(SBEMFϓϥάΠϯ ʴIUNMDTTͷ%4-ϥΠϒϥϦɺ֤छ+4 ϥούʔ ϥΠϒϥϦ ,PUMJO+4͕ఏڙ͢ΔϞϊ ,PUMJO͔Β+4΁ͷม׵ɺOQNʹΑΔόʔδϣϯ؅ཧɺ8FCQBDLʹΑΔόϯυϧ શͯΛ,PUMJOͷੈքͰ׬݁ͤ͞ɺϑϩϯτΤϯυ։ൃΛ࣮ݱ͢Δʂ

Slide 9

Slide 9 text

,PUMJO+4ͷྺ࢙ ,PUMJOϦϦʔε w ,PUMJO+4ਖ਼ࣜϦϦʔεɻʮLPUMJOKTʯͰ,PUMJOˠ+4ม׵͕Ͱ͖ΔΑ͏ʹ LPUMJOGSPOUFOEQMVHJOϦϦʔε w (SBEMF͔ΒͷOQNɺ8FCQBDLͷίϚϯυ࣮ߦΛαϙʔτ͢ΔϓϥάΠϯ ,PUMJOϦϦʔε w ,PUMJO.11ొ৔ɻ+7.΍/BUJWFͷϞδϡʔϧͱϩδοΫΛڞ௨Խ ,PUMJOϦϦʔε w LPUMJOKTˠDPNKFUCSBJOTLPUMJOKTʹվ໊ɺLPUMJOGSPOUFOEQMVHJOͷҰ෦ػೳ͕౷߹ w ʮLPUMJOGSPOUFOEQMVHJO͸ࠓޙഇࢭ༧ఆʯͱࠂ஌ ,PUMJOϦϦʔε w 8FCQBDLͷઃఆ߲໨௥Ճɺόάमਖ਼

Slide 10

Slide 10 text

,PUMJOϦϦʔε w ,PUMJO+4ਖ਼ࣜϦϦʔεɻʮLPUMJOKTʯͰ,PUMJOˠ+4ม׵͕Ͱ͖ΔΑ͏ʹ LPUMJOGSPOUFOEQMVHJOϦϦʔε w (SBEMF͔ΒͷOQNɺ8FCQBDLͷίϚϯυ࣮ߦΛαϙʔτ͢ΔϓϥάΠϯ ,PUMJOϦϦʔε w ,PUMJO.11ొ৔ɻ+7.΍/BUJWFͷϞδϡʔϧͱϩδοΫΛڞ௨Խ ,PUMJOϦϦʔε w LPUMJOKTˠDPNKFUCSBJOTLPUMJOKTʹվ໊ɺLPUMJOGSPOUFOEQMVHJOͷҰ෦ػೳ͕౷߹ w ʮLPUMJOGSPOUFOEQMVHJO͸ࠓޙഇࢭ༧ఆʯͱࠂ஌ ,PUMJOϦϦʔε w 8FCQBDLͷઃఆ߲໨௥Ճɺόάमਖ਼ ,PUMJO+4ͷྺ࢙ ,PUMJO.11ͷҰ෦ͱͯ͠ ֤छϓϥάΠϯ͕·ͱ·ΔྲྀΕ

Slide 11

Slide 11 text

,PUMJOϦϦʔε w ,PUMJO+4ਖ਼ࣜϦϦʔεɻʮLPUMJOKTʯͰ,PUMJOˠ+4ม׵͕Ͱ͖ΔΑ͏ʹ LPUMJOGSPOUFOEQMVHJOϦϦʔε w (SBEMF͔ΒͷOQNɺ8FCQBDLͷίϚϯυ࣮ߦΛαϙʔτ͢ΔϓϥάΠϯ ,PUMJOϦϦʔε w ,PUMJO.11ొ৔ɻ+7.΍/BUJWFͷϞδϡʔϧͱϩδοΫΛڞ௨Խ ,PUMJOϦϦʔε w LPUMJOKTˠDPNKFUCSBJOTLPUMJOKTʹվ໊ɺLPUMJOGSPOUFOEQMVHJOͷҰ෦ػೳ͕౷߹ w ʮLPUMJOGSPOUFOEQMVHJO͸ࠓޙഇࢭ༧ఆʯͱࠂ஌ ,PUMJOϦϦʔε w 8FCQBDLͷઃఆ߲໨௥Ճɺόάमਖ਼ ,PUMJO+4ͷྺ࢙ ͜ͷ࣌ظͷ৘ใ͕݁ߏଟ͍ ࠓޙݹ͘ͳΔͷͰ஫ҙʂ

Slide 12

Slide 12 text

݁ہͲΜͳϞϊ͕࡞ΕΔͷ w ࠷ऴతͳ੒Ռ෺ˠ+4ϑΝΠϧɺ8FCQBDLͷόϯυϧϑΝΠϧ w +4Ͱ࡞ΕΔϞϊ͸શͯ,PUMJO+4Ͱ࡞Δ͜ͱ͕Մೳʂ ཧ࿦্ w ࣄྫ঺հ w ࣗ෼ͷϙʔτϑΥϦΦαΠτ w খௗ͞Μͷࣗशࣨ ϒϥ΢β্Ͱ,PUMJOΛֶ΂ΔֶशαΠτ

Slide 13

Slide 13 text

ࣄྫ ϙʔτϑΥϦΦαΠτ (JUIVCTVCSPIQPSUGPMJP ࢖༻ϥΠϒϥϦɾ"1* w ,PUMJO+4 W w 3FBDUKT w .BUFSJBM6* ˠ'JSFCBTF)PTUJOHͰϗεςΟϯά ɹ-JOLTVCSPINF w (PPHMF.BQ"1* w SFBDUTXJQFBCMFWJFXT

Slide 14

Slide 14 text

ࣄྫ খௗ͞Μͷࣗशࣨ (JUIVCTVCSPIPUPOBTIJLPUMJOEFW ػೳ w ϒϥ΢β্Ͱ,PUMJO,PBOTͷ՝୊͕Ͱ͖Δ w ՝୊ͷΫϦΞɺίϯύΠϧΤϥʔ౳ʹ ɹ߹ΘͤͯϨεϙϯεΛฦ͢ ˠখௗ͞ΜͱϖΞϓϩ͠ͳ͕Β,PUMJOΛֶश w ,PUMJOͷ3&1-LPUMJOQMBZHSPVOE w ϖʔδભҠ3FBDI3PVUFS খௗ͞Μ

Slide 15

Slide 15 text

No content

Slide 16

Slide 16 text

ࣄྫ খௗ͞Μͷࣗशࣨ (JUIVCTVCSPIPUPOBTIJLPUMJOEFW ࢓༷ϥΠϒϥϦ w ,PUMJO+4 W w 3FBDUKT w .BUFSJBM6* ˠϧʔςΟϯάϥΠϒϥϦΛ࢖ͬͨ41" ɹ খௗ͞Μ w 3FBDI3PVUFS w LPUMJOQMBZHSPVOE

Slide 17

Slide 17 text

,PUMJO+4ɺҙ֎ͱͰ͖Δࢠ Կ͔࡞Γͨ͘ͳ͖ͬͯͨ

Slide 18

Slide 18 text

,PUMJO+43FBDUKTͰ ʮ)FMMP 8PSMEʯ

Slide 19

Slide 19 text

,PUMJO+4Ͱ3FBDUΞϓϦΛ࡞Δ ,PUMJOͰॻ͍ͨίʔυΛ௚઀OQN8FCQBDLͰϏϧυ w OQNɺ8FCQBDLͷίϚϯυΛ௚઀࣮ߦ +4ͷੈքʹ,PUMJOΛಋೖ͢Δ w ϝϦοτ+4Ͱॻ͔ΕͨطଘͷϓϩδΣΫτʹಋೖ͠΍͍͢ w σϝϦοτOQNɺ8FCQBDL͕ͱ͖ͬͭʹ͍͘ ಛʹ,PUMJOΤϯδχΞ

Slide 20

Slide 20 text

,PUMJO+4Ͱ3FBDUΞϓϦΛ࡞Δ ,PUMJOͰॻ͍ͨίʔυΛ(SBEMFͰϏϧυ w (SBEMFܦ༝ͰOQNɺ8FCQBDLͷίϚϯυΛ࣮ߦ͢Δ w ϝϦοτ࢖͍׳Εͨ(SBEMFͰॻ͚Δɺ,PUMJO%4-ͷଘࡏ ,PUMJO.11ͱͷ਌࿨ੑ͕ߴ͍ w σϝϦοτطଘͷ+4ϓϩδΣΫτ΁ͷಋೖ͸ݫ͍͠ɺ৘ใ͕গͳ͍

Slide 21

Slide 21 text

,PUMJO+4OQN w +FU#SBJOTDSFBUFSFBDULPUMJOBQQ w ʮDSFBUFSFBDUBQQʯͷ,PUMJO൛ w ίϚϯυҰൃͰ3FBDUKTͷαϯϓϧΞϓϦΛੜ੒ ཁ/PEFKT ˠ,PUMJO+4ʹΑΔ3FBDUΞϓϦͷ࣮૷ΠϝʔδΛ௫Έ΍͍͢

Slide 22

Slide 22 text

,PUMJO+4OQN w ϞδϡʔϧͷΠϯετʔϧɾϓϩδΣΫτੜ੒ɾ࣮ߦ # インストール $ npm install -g create-react-kotlin-app # プロジェクト生成 $ create-react-kotlin-app my-app # 実行 $ cd my-app/ $ npm start

Slide 23

Slide 23 text

w MPDBMIPTUʹΞΫηε͢Δͱʜ ,PUMJO+4OQN

Slide 24

Slide 24 text

σΟϨΫτϦߏ੒

Slide 25

Slide 25 text

OQNʹΑΔύοέʔδ؅ཧʹඞཁͳ+40/

Slide 26

Slide 26 text

,PUMJO+4ͷϥούʔϞδϡʔϧ͕ ґଘؔ܎ʹ௥ՃࡁΈʂ "devDependencies": { "@jetbrains/gen-idea-libs": "^1.0.11", "@jetbrains/kotlin-extensions": "^1.0.1-pre.58", "@jetbrains/kotlin-react": "^16.5.2-pre.58", "@jetbrains/kotlin-react-dom": "^16.5.2-pre.58", "@jetbrains/kotlin-webpack-plugin": "^2.0.3", "@jetbrains/ts2kt-automator": "^1.0.12", "kotlin": "^1.3.0", "kotlinx-html": “^0.6.11", … }

Slide 27

Slide 27 text

,PUMJO+4ͷίʔυDTTϦιʔεϑΝΠϧ

Slide 28

Slide 28 text

JOEFYLUͷதʹNBJOϝιου͕࣮૷ ˠ࠷ॳʹݺͼग़͞ΕΔ

Slide 29

Slide 29 text

package index import … fun main(args: Array) { requireAll(require.context("src", true, js("/\\.css$/"))) render(document.getElementById("root")) { child(App::class) { } } }

Slide 30

Slide 30 text

package index import … fun main(args: Array) { requireAll(require.context("src", true, js("/\\.css$/"))) render(document.getElementById("root")) { child(App::class) { } } } TSDҎԼͷDTTΛҰׅಡΈࠐΈ

Slide 31

Slide 31 text

package index import … fun main(args: Array) { requireAll(require.context("src", true, js("/\\.css$/"))) render(document.getElementById("root")) { child(App::class) { } } } "QQίϯϙʔωϯτΛSFOEFS

Slide 32

Slide 32 text

package app import … class App : RComponent() { override fun RBuilder.render() { div("App-header") { child(Logo::class) { } h2 { +"Welcome to React with Kotlin" } } p("App-intro") { +"To get started, edit " code { +"app/App.kt" } +" and save to reload." } p("App-ticker") { child(Ticker:class) { attrs.startFrom = 0 } } } }

Slide 33

Slide 33 text

package app import … class App : RComponent() { override fun RBuilder.render() { div("App-header") { child(Logo::class) { } h2 { +"Welcome to React with Kotlin" } } p("App-intro") { +"To get started, edit " code { +"app/App.kt" } +" and save to reload." } p("App-ticker") { child(Ticker:class) { attrs.startFrom = 0 } } } } 3$PNQPOFOUΛܧঝ$PNQPOFOUఆٛ

Slide 34

Slide 34 text

package app import … class App : RComponent() { override fun RBuilder.render() { div("App-header") { child(Logo::class) { } h2 { +"Welcome to React with Kotlin" } } p("App-intro") { +"To get started, edit " code { +"app/App.kt" } +" and save to reload." } p("App-ticker") { child(Ticker:class) { attrs.startFrom = 0 } } } } SFOEFSϝιου಺ʹIUNMΛ%4-Ͱهड़

Slide 35

Slide 35 text

package app import … class App : RComponent() { override fun RBuilder.render() { div("App-header") { child(Logo::class) { } h2 { +"Welcome to React with Kotlin" } } p("App-intro") { +"To get started, edit " code { +"app/App.kt" } +" and save to reload." } p("App-ticker") { child(Ticker:class) { attrs.startFrom = 0 } } } } EJWDMBTT/BNFl"QQIFBEFSzʜEJW

Slide 36

Slide 36 text

package app import … class App : RComponent() { override fun RBuilder.render() { div("App-header") { child(Logo::class) { } h2 { +"Welcome to React with Kotlin" } } p("App-intro") { +"To get started, edit " code { +"app/App.kt" } +" and save to reload." } p("App-ticker") { child(Ticker:class) { attrs.startFrom = 0 } } } } I8FMDPNFUP3FBDUXJUI,PUMJOI

Slide 37

Slide 37 text

package app import … class App : RComponent() { override fun RBuilder.render() { div("App-header") { child(Logo::class) { } h2 { +"Welcome to React with Kotlin" } } p("App-intro") { +"To get started, edit " code { +"app/App.kt" } +" and save to reload." } p("App-ticker") { child(Ticker:class) { attrs.startFrom = 0 } } } } ճస͢Δϩΰͷදࣔίϯϙʔωϯτ

Slide 38

Slide 38 text

package app import … class App : RComponent() { override fun RBuilder.render() { div("App-header") { child(Logo::class) { } h2 { +"Welcome to React with Kotlin" } } p("App-intro") { +"To get started, edit " code { +"app/App.kt" } +" and save to reload." } p("App-ticker") { child(Ticker:class) { attrs.startFrom = 0 } } } } ܦա࣌ؒදࣔͷίϯϙʔωϯτ

Slide 39

Slide 39 text

interface TickerProps : RProps { var startFrom: Int } interface TickerState : RState { var secondsElapsed: Int } class Ticker(props: TickerProps) : RComponent(props) { override fun TickerState.init(props: TickerProps) { secondsElapsed = props.startFrom } var timerID: Int? = null override fun componentDidMount() { timerID = window.setInterval({ setState { secondsElapsed += 1 } }, 1000) } override fun componentWillUnmount() { window.clearInterval(timerID!!) } override fun RBuilder.render() { +"This app has been running for ${state.secondsElapsed} seconds." } }

Slide 40

Slide 40 text

interface TickerProps : RProps { var startFrom: Int } interface TickerState : RState { var secondsElapsed: Int } class Ticker(props: TickerProps) : RComponent(props) { override fun TickerState.init(props: TickerProps) { secondsElapsed = props.startFrom } var timerID: Int? = null override fun componentDidMount() { timerID = window.setInterval({ setState { secondsElapsed += 1 } }, 1000) } override fun componentWillUnmount() { window.clearInterval(timerID!!) } override fun RBuilder.render() { +"This app has been running for ${state.secondsElapsed} seconds." } } 31SPQTΛܧঝͨ͠5JDLFS1SPQT ˠ਌ίϯϙʔωϯτ͔Β ɹड͚औΔ஋ͷఆٛ

Slide 41

Slide 41 text

interface TickerProps : RProps { var startFrom: Int } interface TickerState : RState { var secondsElapsed: Int } class Ticker(props: TickerProps) : RComponent(props) { override fun TickerState.init(props: TickerProps) { secondsElapsed = props.startFrom } var timerID: Int? = null override fun componentDidMount() { timerID = window.setInterval({ setState { secondsElapsed += 1 } }, 1000) } override fun componentWillUnmount() { window.clearInterval(timerID!!) } override fun RBuilder.render() { +"This app has been running for ${state.secondsElapsed} seconds." } } 34UBUFΛܧঝͨ͠5JDLFS4UBUF ˠ5JDLFSίϯϙʔωϯτͷঢ়ଶ

Slide 42

Slide 42 text

interface TickerProps : RProps { var startFrom: Int } interface TickerState : RState { var secondsElapsed: Int } class Ticker(props: TickerProps) : RComponent(props) { override fun TickerState.init(props: TickerProps) { secondsElapsed = props.startFrom } var timerID: Int? = null override fun componentDidMount() { timerID = window.setInterval({ setState { secondsElapsed += 1 } }, 1000) } override fun componentWillUnmount() { window.clearInterval(timerID!!) } override fun RBuilder.render() { +"This app has been running for ${state.secondsElapsed} seconds." } } JOJUؔ਺Ͱܦա࣌ؒͷॳظԽ

Slide 43

Slide 43 text

interface TickerProps : RProps { var startFrom: Int } interface TickerState : RState { var secondsElapsed: Int } class Ticker(props: TickerProps) : RComponent(props) { override fun TickerState.init(props: TickerProps) { secondsElapsed = props.startFrom } var timerID: Int? = null override fun componentDidMount() { timerID = window.setInterval({ setState { secondsElapsed += 1 } }, 1000) } override fun componentWillUnmount() { window.clearInterval(timerID!!) } override fun RBuilder.render() { +"This app has been running for ${state.secondsElapsed} seconds." } } ඵ͝ͱʹTUBUFͷ஋Λߋ৽ ˞TFU4UBUFϝιουͰ஋ߋ৽ SFOEFSϝιουͷݺͼग़͠

Slide 44

Slide 44 text

interface TickerProps : RProps { var startFrom: Int } interface TickerState : RState { var secondsElapsed: Int } class Ticker(props: TickerProps) : RComponent(props) { override fun TickerState.init(props: TickerProps) { secondsElapsed = props.startFrom } var timerID: Int? = null override fun componentDidMount() { timerID = window.setInterval({ setState { secondsElapsed += 1 } }, 1000) } override fun componentWillUnmount() { window.clearInterval(timerID!!) } override fun RBuilder.render() { +"This app has been running for ${state.secondsElapsed} seconds." } } ܦա࣌ؒͷදࣔ

Slide 45

Slide 45 text

ίʔυൺֱ class App extends React.Component { render() { return (

Welcome to React with Kotlin

To get started, edit app/App.kt and save to reload.

); } } class App : RComponent() { override fun RBuilder.render() { div("App-header") { child(Logo::class) { } h2 { +"Welcome to React with Kotlin" } } p("App-intro") { +"To get started, edit " code { +"app/App.kt" } +" and save to reload." } p("App-ticker") { child(Ticker:class) { attrs.startFrom = 0 } } } } +4 ,PUMJO

Slide 46

Slide 46 text

w +4ϥΠϒϥϦΛ௥Ճ͍ͨ͠ʂ w npm install hoge --save w ௥Ճͨ͠+4ϥΠϒϥϦΛ,PUMJOͰѻ͍͍ͨʂ w ޙड़ w 8FCQBDLͷઃఆΛΧελϚΠζ͍ͨ͠ʂ w npm run eject ͰઃఆϑΝΠϧΛग़ྗՄ ,PUMJO+4OQN

Slide 47

Slide 47 text

*OUFMMJ+*%&"6MUJNBUFͰʮ)FMMP 8PSMEʯ·Ͱ ,PUMJO+4(SBEMF $SFBUF/FX1SPKFDU ˠ(SBEMF ˠ,PUMJO+4GPSCSPXTFS ˠ/FYU

Slide 48

Slide 48 text

,PUMJO+4(SBEMF w (SPVQ*E w "SUJGBDU*E w 1SPKFDUOBNF w 1SPKFDUMPDBUJPO ͓޷ΈͰ

Slide 49

Slide 49 text

,PUMJO+4(SBEMF ϓϩδΣΫτͷ਽ܗ͕ੜ੒ʂ ΍Δ͜ͱ w (SBEMFʹґଘؔ܎ɺϏϧυઃఆ௥Ճ w ,PUMJO+4ͷίʔυ௥Ճ w JOEFYIUNMͷ࡞੒ 4BNQMF3FQPTVCSPILPUMJOSFBDUTBNQMF

Slide 50

Slide 50 text

(SBEMF1MVHJOͷࢦఆSFQPTJUPSJFTͷࢦఆ ,PUMJO+4(SBEMF plugins { id 'org.jetbrains.kotlin.js' version '1.3.50' } group 'subroh0508.net' version '1.0-SNAPSHOT' repositories { jcenter() mavenCentral() maven { url "http://dl.bintray.com/kotlin/kotlin-js-wrappers" } maven { url 'https://plugins.gradle.org/m2/' } }

Slide 51

Slide 51 text

8FCQBDLͷઃఆ ,PUMJO+4(SBEMF kotlin { target { browser { runTask { devServer = new KotlinWebpackConfig.DevServer( true, false, true, true, false, 8080, null, ["$projectDir/src/main/resources".toString()] ) archiveFileName = "kotlin-react-sample.js" } } }

Slide 52

Slide 52 text

8FCQBDLͷઃఆ ,PUMJO+4(SBEMF kotlin { target { browser { runTask { devServer = new KotlinWebpackConfig.DevServer( true, false, true, true, false, 8080, null, ["$projectDir/src/main/resources".toString()] ) archiveFileName = "kotlin-react-sample.js" } } } CSPXTFSϒϩοΫ಺Ͱ 8FCQBDLͷઃఆΛهड़

Slide 53

Slide 53 text

kotlin { target { browser { runTask { devServer = new KotlinWebpackConfig.DevServer( true, false, true, true, false, 8080, null, ["$projectDir/src/main/resources".toString()] ) archiveFileName = "kotlin-react-sample.js" } } } 8FCQBDLͷઃఆ ,PUMJO+4(SBEMF QPSUɾQSPYZɾDPOUFOU#BTF౳Λࢦఆ ˠϦιʔεσΟϨΫτϦͷύεΛ DPOUFOU#BTFʹࢦఆ

Slide 54

Slide 54 text

kotlin { target { browser { runTask { devServer = new KotlinWebpackConfig.DevServer( true, false, true, true, false, 8080, null, ["$projectDir/src/main/resources".toString()] ) archiveFileName = "kotlin-react-sample.js" } } } 8FCQBDLͷઃఆ ,PUMJO+4(SBEMF BSDIJWF'JMF/BNF ˠόϯυϧޙͷϑΝΠϧ໊

Slide 55

Slide 55 text

ϥΠϒϥϦͷґଘؔ܎ ,PUMJO+4(SBEMF sourceSets { main { dependencies { implementation "org.jetbrains.kotlin:kotlin-stdlib-js" implementation "org.jetbrains.kotlinx:kotlinx-html-js:0.6.12" implementation "org.jetbrains:kotlin-react:16.9.0-pre.83-kotlin-1.3.41" implementation "org.jetbrains:kotlin-react-dom:16.9.0-pre.83-kotlin-1.3.41" implementation "org.jetbrains:kotlin-styled:1.0.0-pre.83-kotlin-1.3.41" implementation npm("core-js", "~3.1.4") implementation npm("react", "16.9.0") implementation npm("react-dom", "16.9.0") implementation npm("styled-components", "3.4.10") implementation npm("inline-style-prefixer", "5.0.4") } } }

Slide 56

Slide 56 text

sourceSets { main { dependencies { implementation "org.jetbrains.kotlin:kotlin-stdlib-js" implementation "org.jetbrains.kotlinx:kotlinx-html-js:0.6.12" implementation "org.jetbrains:kotlin-react:16.9.0-pre.83-kotlin-1.3.41" implementation "org.jetbrains:kotlin-react-dom:16.9.0-pre.83-kotlin-1.3.41" implementation "org.jetbrains:kotlin-styled:1.0.0-pre.83-kotlin-1.3.41" implementation npm("core-js", "~3.1.4") implementation npm("react", "16.9.0") implementation npm("react-dom", "16.9.0") implementation npm("styled-components", "3.4.10") implementation npm("inline-style-prefixer", "5.0.4") } } } ϥΠϒϥϦͷґଘؔ܎ ,PUMJO+4(SBEMF ,PUMJO+4ͷඪ४ϥΠϒϥϦ

Slide 57

Slide 57 text

ϥΠϒϥϦͷґଘؔ܎ sourceSets { main { dependencies { implementation "org.jetbrains.kotlin:kotlin-stdlib-js" implementation "org.jetbrains.kotlinx:kotlinx-html-js:0.6.12" implementation "org.jetbrains:kotlin-react:16.9.0-pre.83-kotlin-1.3.41" implementation "org.jetbrains:kotlin-react-dom:16.9.0-pre.83-kotlin-1.3.41" implementation "org.jetbrains:kotlin-styled:1.0.0-pre.83-kotlin-1.3.41" implementation npm("core-js", "~3.1.4") implementation npm("react", "16.9.0") implementation npm("react-dom", "16.9.0") implementation npm("styled-components", "3.4.10") implementation npm("inline-style-prefixer", "5.0.4") } } } ,PUMJO+4(SBEMF LPUMJOYIUNMIUNMͷ%4-ϥΠϒϥϦ LPUMJOSFBDU3FBDUͷϥούʔϥΠϒϥϦ

Slide 58

Slide 58 text

sourceSets { main { dependencies { implementation "org.jetbrains.kotlin:kotlin-stdlib-js" implementation "org.jetbrains.kotlinx:kotlinx-html-js:0.6.12" implementation "org.jetbrains:kotlin-react:16.9.0-pre.83-kotlin-1.3.41" implementation "org.jetbrains:kotlin-react-dom:16.9.0-pre.83-kotlin-1.3.41" implementation "org.jetbrains:kotlin-styled:1.0.0-pre.83-kotlin-1.3.41" implementation npm("core-js", "~3.1.4") implementation npm("react", "16.9.0") implementation npm("react-dom", "16.9.0") implementation npm("styled-components", "3.4.10") implementation npm("inline-style-prefixer", "5.0.4") } } } ϥΠϒϥϦͷґଘؔ܎ ,PUMJO+4(SBEMF +4ͷϥΠϒϥϦ͸OQN Ͱࢦఆ

Slide 59

Slide 59 text

,PUMJO+4ͷίʔσΟϯά ,PUMJO+4(SBEMF // main.kt fun main() { render(document.getElementById("root")) { child(App::class) { } } } // App.kt class App : RComponent() { override fun RBuilder.render() { div { +"Hello, World!" } } }

Slide 60

Slide 60 text

JOEFYIUNMͷ࡞੒ ,PUMJO+4(SBEMF Title
ˡIUNMϑΝΠϧΛ SFTPVSDFTҎԼʹ഑ஔ

Slide 61

Slide 61 text

,PUMJO+4(SBEMF ࣮ߦʂ $ ./gradlew run ,PUMJOͷ8FCΞϓϦɺ׬੒ʂ

Slide 62

Slide 62 text

ಈ͖Λ͚͍ͭͨ ྫΧ΢ϯλʔ interface AppState : RState { var count: Int } class App : RComponent() { override fun AppState.init() { count = 0 } private fun onClickedButton() { setState { count += 1 } } override fun RBuilder.render() { div { +"count: ${state.count}" } button { attrs.onClickFunction = { onClickedButton() } +"click!" } } }

Slide 63

Slide 63 text

interface AppState : RState { var count: Int } class App : RComponent() { override fun AppState.init() { count = 0 } private fun onClickedButton() { setState { count += 1 } } override fun RBuilder.render() { div { +"count: ${state.count}" } button { attrs.onClickFunction = { onClickedButton() } +"click!" } } } TUBUFͷܕఆٛ ಈ͖Λ͚͍ͭͨ ྫΧ΢ϯλʔ

Slide 64

Slide 64 text

interface AppState : RState { var count: Int } class App : RComponent() { override fun AppState.init() { count = 0 } private fun onClickedButton() { setState { count += 1 } } override fun RBuilder.render() { div { +"count: ${state.count}" } button { attrs.onClickFunction = { onClickedButton() } +"click!" } } } TUBUFͷॳظԽ ಈ͖Λ͚͍ͭͨ ྫΧ΢ϯλʔ

Slide 65

Slide 65 text

interface AppState : RState { var count: Int } class App : RComponent() { override fun AppState.init() { count = 0 } private fun onClickedButton() { setState { count += 1 } } override fun RBuilder.render() { div { +"count: ${state.count}" } button { attrs.onClickFunction = { onClickedButton() } +"click!" } } } ϘλϯΫϦοΫ࣌ͷίʔϧόοΫؔ਺ ˠTFU4UBUFϝιουͰΧ΢ϯτΛ૿΍͢ ಈ͖Λ͚͍ͭͨ ྫΧ΢ϯλʔ

Slide 66

Slide 66 text

interface AppState : RState { var count: Int } class App : RComponent() { override fun AppState.init() { count = 0 } private fun onClickedButton() { setState { count += 1 } } override fun RBuilder.render() { div { +"count: ${state.count}" } button { attrs.onClickFunction = { onClickedButton() } +"click!" } } } Χ΢ϯτͷදࣔͱίʔϧόοΫͷࢦఆ ˠBUUSTPO$MJDL'VODUJPO\^ ಈ͖Λ͚͍ͭͨ ྫΧ΢ϯλʔ

Slide 67

Slide 67 text

ελΠϧΛ͚͍ͭͨ DTTJO,PUMJO override fun RBuilder.render() { div { +"count: ${state.count}" } styledButton { css { width = 200.px height = 100.px backgroundColor = Color.aqua } attrs.onClickFunction = { onClickedButton() } +"click!" } }

Slide 68

Slide 68 text

ελΠϧΛ͚͍ͭͨ DTTJO,PUMJO override fun RBuilder.render() { div { +"count: ${state.count}" } styledButton { css { width = 200.px height = 100.px backgroundColor = Color.aqua } attrs.onClickFunction = { onClickedButton() } +"click!" } } TUZMFE#VUUPOʹ͢Δͱ DTT IBOEMFS3VMF4FU ϝιου͕ੜ͑Δ

Slide 69

Slide 69 text

ελΠϧΛ͚͍ͭͨ DTTJO,PUMJO override fun RBuilder.render() { div { +"count: ${state.count}" } styledButton { css { width = 200.px height = 100.px backgroundColor = Color.aqua } attrs.onClickFunction = { onClickedButton() } +"click!" } } DTTϒϩοΫͷதͰελΠϧΛهड़ ˞TUZMFEDPNQPOFOUͷػೳ

Slide 70

Slide 70 text

؆୯ͳ8FCϖʔδ͸࡞Εͨ ΋ͬͱϦονͳ͜ͱ͍ͨ͠

Slide 71

Slide 71 text

,PUMJO+4ΞϓϦ΁ͷ +4੡ϥΠϒϥϦͷಋೖ

Slide 72

Slide 72 text

+4੡ϥΠϒϥϦͷಋೖ ಋೖͷखॱ w OQN(SBEMFʹ+4੡ϥΠϒϥϦʹର͢Δґଘؔ܎௥ه w ΞϊςʔγϣϯΛ࢖͍ɺ+4ϥΠϒϥϦΛ,PUMJOίʔυʹΠϯϙʔτ w Ћ ܕఆٛɺϝιουఆٛ ˠ+4ϥΠϒϥϦΛʮ,PUMJOΒ͘͠ʯѻ͏ͨΊͷԼ͝͠Β͑ ,PUMJO+4ಠࣗͷػೳΛۦ࢖͠ɺ࣮ݱ ϋϚΓͲ͜Ζʂ

Slide 73

Slide 73 text

+4੡ϥΠϒϥϦͷಋೖ ґଘؔ܎௥Ճ ྫSFBDUTXJQFBCMFWJFXT w OQNͷ৔߹ npm install react-swipeable-views --save w (SBEMFͷ৔߹CVJMEHSBEMFʹ௥ه sourceSets { main { dependencies { ... implementation npm("react-swipeable-views") ... } } }

Slide 74

Slide 74 text

+4੡ϥΠϒϥϦͷಋೖ !+T.PEVMFΞϊςʔγϣϯ w +4ϥΠϒϥϦΛ,PUMJOͷੈքʹΠϯϙʔτ͢ΔΞϊςʔγϣϯ @JsModule("react-swipeable-views") private external val reactSwipeableViewModule: dynamic fun test() { reactSwipeableViewModule.default.onChangeIndex = { ... } }

Slide 75

Slide 75 text

+4੡ϥΠϒϥϦͷಋೖ !+T.PEVMFΞϊςʔγϣϯ w +4ϥΠϒϥϦΛ,PUMJOͷੈքʹΠϯϙʔτ͢ΔΞϊςʔγϣϯ @JsModule("react-swipeable-views") private external val reactSwipeableViewModule: dynamic fun test() { reactSwipeableViewModule.default.onChangeIndex = { ... } } +4ϥΠϒϥϦΛΠϯϙʔτ PO$IBOHF*OEFYʹ ϥϜμࣜΛ୅ೖ Ξϊςʔγϣϯ͚ͭͩʂ +4੡ϥΠϒϥϦΛ,PUMJOͷੈքͰ ҰԠ͸ ѻ͑Δʂ

Slide 76

Slide 76 text

+4੡ϥΠϒϥϦͷಋೖ !+T.PEVMFΞϊςʔγϣϯ w +4ϥΠϒϥϦΛ,PUMJOͷੈքʹΠϯϙʔτ͢ΔΞϊςʔγϣϯ @JsModule("react-swipeable-views") private external val reactSwipeableViewModule: dynamic fun test() { reactSwipeableViewModule.default.onChangeIndex = { ... } } EZOBNJDܕʜʁ

Slide 77

Slide 77 text

+4੡ϥΠϒϥϦͷಋೖ EZOBNJDܕ w ,PUMJOͱ+4ͷڮ౉͠Λ୲͏ܕ w ,PUMJOͷੈքͰ+4ͷΦϒδΣΫτΛͦͷ··දݱ͢Δ͜ͱ͕Ͱ͖Δ // { foo: 'foo', bar: { hoge: 111 } }をKotlinで扱う場合 val jsObject: dynamic = js("{ foo: 'foo', bar: { hoge: 111 } }") print(jsObject["foo"]) // => 'foo' print(jsObject["bar"]["hoge"]) // => 111 jsObject["aaa"]["bbb"] = "add from kotlin" print(jsObject["aaa"]["bbb"]) // => add from kotlin

Slide 78

Slide 78 text

+4੡ϥΠϒϥϦͷಋೖ EZOBNJDܕ w ,PUMJOͱ+4ͷڮ౉͠Λ୲͏ܕ w ,PUMJOͷੈքͰ+4ͷΦϒδΣΫτΛͦͷ··දݱ͢Δ͜ͱ͕Ͱ͖Δ // { foo: 'foo', bar: { hoge: 111 } }をKotlinで扱う場合 val jsObject: dynamic = js("{ foo: 'foo', bar: { hoge: 111 } }") print(jsObject["foo"]) // => 'foo' print(jsObject["bar"]["hoge"]) // => 111 jsObject["aaa"]["bbb"] = "add from kotlin" print(jsObject["aaa"]["bbb"]) // => add from kotlin +4ͷΦϒδΣΫτΛੜ੒

Slide 79

Slide 79 text

+4੡ϥΠϒϥϦͷಋೖ EZOBNJDܕ w ,PUMJOͱ+4ͷڮ౉͠Λ୲͏ܕ w ,PUMJOͷੈքͰ+4ͷΦϒδΣΫτΛͦͷ··දݱ͢Δ͜ͱ͕Ͱ͖Δ // { foo: 'foo', bar: { hoge: 111 } }をKotlinで扱う場合 val jsObject: dynamic = js("{ foo: 'foo', bar: { hoge: 111 } }") print(jsObject["foo"]) // => 'foo' print(jsObject["bar"]["hoge"]) // => 111 jsObject["aaa"]["bbb"] = "add from kotlin" print(jsObject["aaa"]["bbb"]) // => add from kotlin ଘࡏ͢ΔΩʔͷ஋Λऔͬͯ͘Δ

Slide 80

Slide 80 text

+4੡ϥΠϒϥϦͷಋೖ EZOBNJDܕ w ,PUMJOͱ+4ͷڮ౉͠Λ୲͏ܕ w ,PUMJOͷੈքͰ+4ͷΦϒδΣΫτΛͦͷ··දݱ͢Δ͜ͱ͕Ͱ͖Δ // { foo: 'foo', bar: { hoge: 111 } }をKotlinで扱う場合 val jsObject: dynamic = js("{ foo: 'foo', bar: { hoge: 111 } }") print(jsObject["foo"]) // => 'foo' print(jsObject["bar"]["hoge"]) // => 111 jsObject["aaa"]["bbb"] = "add from kotlin" print(jsObject["aaa"]["bbb"]) // => add from kotlin ଘࡏ͠ͳ͍Ωʔͷ஋Λ +4ʹ͍ۙจ๏Ͱ୅ೖͰ͖ͯ͠·͏

Slide 81

Slide 81 text

+4੡ϥΠϒϥϦͷಋೖ EZOBNJDܕ w ,PUMJOͱ+4ͷڮ౉͠Λ୲͏ܕ w ,PUMJOͷੈքͰ+4ͷΦϒδΣΫτΛͦͷ··දݱ͢Δ͜ͱ͕Ͱ͖Δ // { foo: 'foo', bar: { hoge: 111 } }をKotlinで扱う場合 val jsObject: dynamic = js("{ foo: 'foo', bar: { hoge: 111 } }") print(jsObject.foo) // => 'foo' print(jsObject.bar.hoge) // => 111 jsObject.aaa.bbb = "add from kotlin" // => Error! ͜͏ͳͬͯཉ͍͠

Slide 82

Slide 82 text

FYUFSOBMम০ࢠ w ,PUMJOͷܕఆٛͱ+4ͷΦϒδΣΫτΛϚοϐϯά͢Δम০ࢠ external interface TestObject { var foo: String var bar: TestChildObject } external interface TestChildObject { var hoge: String } val jsObject: TestObject = js("{ foo: 'foo', bar: { hoge: '111' } }") print(jsObject.foo) // => 'foo' print(jsObject.bar.hoge) // => 111 5ZQF4DSJQUͷܕఆٛϑΝΠϧͱ ໾ׂ͸ಉ͡ +4੡ϥΠϒϥϦͷಋೖ

Slide 83

Slide 83 text

+4੡ϥΠϒϥϦΛʮ,PUMJOΒ͘͠ʯѻ͏ʹ͸ w FYUFSOBMम০ࢠΛ͚ͭͨΠϯλʔϑΣʔεͰܕఆٛ w +4ͷؔ਺Λ,PUMJOΒ͘͠ݺ΂ΔΑ͏ʹؔ਺ఆٛ +4੡ϥΠϒϥϦͷಋೖ @JsModule("react-swipeable-views") private external val reactSwipeableViewModule: dynamic external interface ReactSwipeableProps : RProps { var onChangeIndex: (Int, Int, ChangeReason) -> Unit } val RBuilder.swipeableViews: RClass get() = reactSwipeableViewModule.default as RClass

Slide 84

Slide 84 text

+4੡ϥΠϒϥϦΛʮ,PUMJOΒ͘͠ʯѻ͏ʹ͸ w FYUFSOBMम০ࢠΛ͚ͭͨΠϯλʔϑΣʔεͰܕఆٛ w +4ͷؔ਺Λ,PUMJOΒ͘͠ݺ΂ΔΑ͏ʹؔ਺ఆٛ +4੡ϥΠϒϥϦͷಋೖ @JsModule("react-swipeable-views") private external val reactSwipeableViewModule: dynamic external interface ReactSwipeableProps : RProps { var onChangeIndex: (Int, Int, ChangeReason) -> Unit } val RBuilder.swipeableViews: RClass get() = reactSwipeableViewModule.default as RClass FYUFSOBMJOUFSGBDFΛఆٛ ˠϓϩύςΟʮPO$IBOHF*OEFYʯ͕ ɹଘࡏ͢Δ͜ͱΛڭ͑ࠐ·ͤΔ

Slide 85

Slide 85 text

+4੡ϥΠϒϥϦΛʮ,PUMJOΒ͘͠ʯѻ͏ʹ͸ w FYUFSOBMम০ࢠΛ͚ͭͨΠϯλʔϑΣʔεͰܕఆٛ w +4ͷؔ਺Λ,PUMJOΒ͘͠ݺ΂ΔΑ͏ʹؔ਺ఆٛ +4੡ϥΠϒϥϦͷಋೖ @JsModule("react-swipeable-views") private external val reactSwipeableViewModule: dynamic external interface ReactSwipeableProps : RProps { var onChangeIndex: (Int, Int, ChangeReason) -> Unit } val RBuilder.swipeableViews: RClass get() = reactSwipeableViewModule.default as RClass Πϯϙʔτͨ͠ϞδϡʔϧΛ3$MBTT31SPQTʹΩϟετ

Slide 86

Slide 86 text

+4੡ϥΠϒϥϦΛʮ,PUMJOΒ͘͠ʯѻ͏ʹ͸ w FYUFSOBMम০ࢠΛ͚ͭͨΠϯλʔϑΣʔεͰܕఆٛ w +4ͷؔ਺Λ,PUMJOΒ͘͠ݺ΂ΔΑ͏ʹؔ਺ఆٛ +4੡ϥΠϒϥϦͷಋೖ fun ReactSwipeableProps.onChangeIndex(block: (Int) -> Unit) { onChangeIndex = { index: Int, _, _ -> block(index) } } // RComponentクラス内 override fun RBuilder.render() { swipeableViews { attrs.onChangeIndex { i -> setState { tabNumber = i } } } }

Slide 87

Slide 87 text

+4੡ϥΠϒϥϦΛʮ,PUMJOΒ͘͠ʯѻ͏ʹ͸ w FYUFSOBMम০ࢠΛ͚ͭͨΠϯλʔϑΣʔεͰܕఆٛ w +4ͷؔ਺Λ,PUMJOΒ͘͠ݺ΂ΔΑ͏ʹؔ਺ఆٛ +4੡ϥΠϒϥϦͷಋೖ fun ReactSwipeableProps.onChangeIndex(block: (Int) -> Unit) { onChangeIndex = { index: Int, _, _ -> block(index) } } // RComponentクラス内 override fun RBuilder.render() { swipeableViews { attrs.onChangeIndex { i -> setState { tabNumber = i } } } } 1SPQTͷ֦ுؔ਺ͱͯ͠ ηολʔΛఆٛ

Slide 88

Slide 88 text

+4੡ϥΠϒϥϦΛʮ,PUMJOΒ͘͠ʯѻ͏ʹ͸ w FYUFSOBMम০ࢠΛ͚ͭͨΠϯλʔϑΣʔεͰܕఆٛ w +4ͷؔ਺Λ,PUMJOΒ͘͠ݺ΂ΔΑ͏ʹؔ਺ఆٛ +4੡ϥΠϒϥϦͷಋೖ fun ReactSwipeableProps.onChangeIndex(block: (Int) -> Unit) { onChangeIndex = { index: Int, _, _ -> block(index) } } // RComponentクラス内 override fun RBuilder.render() { swipeableViews { attrs.onChangeIndex { i -> setState { tabNumber = i } } } } BUUSTϓϩύςΟ͔Β1SPQT͕ੜ͑Δ ˠ֦ுؔ਺ݺͼग़͠

Slide 89

Slide 89 text

ܕఆٛɾؔ਺ఆٛʹ͔͔Δ࿑ྗ w ϥΠϒϥϦʹ͖ͭɺଟͯ͘΋ߦఔ౓ w ඞཁͳྔ͚ͩఆٛ͢Ε͹0, ͨͩ͠ w ڊେͳϥΠϒϥϦͷܕఆٛɾؔ਺ఆٛ͸ਖ਼௚͔ͳΓ͠ΜͲ͍ w 6*ϑϨʔϜϫʔΫ͸ಛʹ τϥΠΞϯυΤϥʔͷαΠΫϧ͕ճͮ͠Β͍ w ྫ3FBDU#PPUTUSBQɺ.BUFSJBM6*FUD +4੡ϥΠϒϥϦͷಋೖ

Slide 90

Slide 90 text

,PUMJO.BUFSJBM6*ͷ঺հ w (JUIVCTVCSPILPUMJONBUFSJBMVJ w ʮ.BUFSJBM6*ʯͷ,PUMJO+4ϥούʔϥΠϒϥϦ .BUFSJBM%FTJHOͳ6*࡞Γ͍ͨʂ ˠ͜ΕΛ࢖͑͹ղܾʂ ɹ,PUMJO+4΁ͷೖ໳͸͔͜͜Βʂ ɹϥΠϒϥϦ੡࡞ͷࢀߟʹ΋ʂ

Slide 91

Slide 91 text

Ͳ͏ͯ͠΋ॻ͖ํ͕෼͔Βͳ͍ʂ w KT ϝιουҾ਺ʹੜͷ+4ίʔυΛจࣈྻͰ౉͢͜ͱ͕Ͱ͖Δ w +4ΛͱΓ͋͑ͣίϐϖˠগͣͭ͠,PUMJOʹม׵ +4੡ϥΠϒϥϦͷಋೖ inline fun Window.initMap() = js("""new window.google.maps.Map( document.getElementById('googleMap'), { center: { lat: 34.740864, lng: 139.391152 }, zoom: 11.3, mapTypeId: 'roadmap' } )""") ྫ(PPHMF.BQ"1*ͷॳظԽίʔυ

Slide 92

Slide 92 text

·ͱΊ ,PUMJO+4ͷ֓ཁɾΞοϓσʔτͷྺ࢙ʹ͍ͭͯղઆ w ౰ॳಠཱͨ͠ϓϥάΠϯ w ݱࡏ,PUMJO.11ͷҰཌྷΛ୲͏ཱͪҐஔ ,PUMJO+4Λ࢖ͬͨ8FCΞϓϦ੡࡞ͷϋϯζΦϯ w OQNͱ(SBEMFɺͲͪΒͰ΋Մ w EZOBNJDͱFYUFSOBM͕࢖͍͜ͳͤΕ͹ɺ+4੡ϥΠϒϥϦΛࣗ༝ʹѻ͑Δ w ࠷ऴखஈͱͯ͠KTϝιου

Slide 93

Slide 93 text

·ͱΊ ,PUMJO+4ͷ͜Ε͔Β w CBDLFOEͱGSPOUFOE͕ͭͷ,PUMJOϓϩδΣΫτʹ·ͱ·Δʂ w EBUBDMBTTͷڞ༗ɺ(SBEMFͰͷϏϧυɺ%4-ͰͷIUNMDTTهड़ ຊ൪ಋೖ΁ͷน w ѹ౗తͳࣄྫɾ৘ใෆ଍ʂɹϥΠϒϥϦ΋·ͩ·ͩগͳ͍ʂ w ؆୯ͳϞϊͰ΋࡞ͬͯެ։ˠ஌ݟͷ஝ੵɺ,PUMJO+4ͷલਐͷҰॿ ,PUMJOͰϑϩϯτΤϯυͷ։ൃ͕Ͱ͖Δͷ͸ָ͍͠ʂ ୔ࢁͷਓ͕৮ͬͯ͘ΕΔͱخ͍͠☺

Slide 94

Slide 94 text

͓·͚ύʔτ ,PUMJO+4ίʔυ୳ࡧ

Slide 95

Slide 95 text

ίʔυϦʔσΟϯά LPUMJOSFBDU ʮ)FMMP 8PSMEʯΛදࣔ͢ΔαϯϓϧΞϓϦ class App : RComponent() { override fun RBuilder.render() { div { +"Hello, World!" } } } 3$PNQPOFOUʁ 3#VJMEFSʁ SFOEFSϝιου͸ ͳ֦ͥுؔ਺ʁ

Slide 96

Slide 96 text

ίʔυϦʔσΟϯά LPUMJOSFBDU LPUMJOSFBDUͷසग़Ϋϥε w 3$MBTT ˠ3FBDU$MBTTͱରԠɺίϯϙʔωϯτͷܕఆٛ w 3$PNQPOFOU3FBDU&MFNFOU ˠ$PNQPOFOU3FBDU&MFNFOUͱରԠɺίϯϙʔωϯτͷΠϯελϯε w 3#VJMEFS ˠ%0.ߏஙɾ$PNQPOFOUͷੜ੒ʹ੹຿Λ࣋ͭLPUMJOSFBDUಠࣗͷΫϥε

Slide 97

Slide 97 text

ίʔυϦʔσΟϯά LPUMJOSFBDU @ReactDsl open class RBuilder { val childList = mutableListOf() fun child(element: ReactElement): ReactElement { childList.add(element) return element } operator fun String.unaryPlus() { childList.add(this) } fun

child(type: Any, props: P, children: List) = child(createElement(type, props, *children.toTypedArray())) fun

child(type: Any, props: P, handler: RHandler

): ReactElement { val children = with(RElementBuilder(props)) { handler() childList } return child(type, props, children) } operator fun

RClass

.invoke(handler: RHandler

) = child(this, jsObject {}, handler) operator fun RProvider.invoke(value: T, handler: RHandler>) = child(this, jsObject { this.value = value }, handler) operator fun RConsumer.invoke(handler: RBuilder.(T) -> Unit) = child(this, jsObject> { this.children = { value -> buildElements { handler(value) } } }) {} fun

RClass

.node( props: P, children: List = emptyList() ) = child(this, clone(props), children) fun

> child(klazz: KClass, handler: RHandler

): ReactElement { val rClass = klazz.js as RClass

return rClass(handler) } inline fun

> child(noinline handler: RHandler

) = child(C::class, handler) fun

> node( klazz: KClass, props: P, children: List = emptyList() ): ReactElement { val rClass = klazz.js as RClass

return rClass.node(props, children) } inline fun

> node(props: P, children: List = emptyList()) = node(C::class, props, children) fun RProps.children() { childList.addAll(Children.toArray(children)) } } 3#VJMEFSΫϥε

Slide 98

Slide 98 text

ίʔυϦʔσΟϯά LPUMJOSFBDU 3#VJMEFSΫϥε w %0.ཁૉΛ֨ೲ͢ΔDIJME-JTUϓϩύςΟΛ࣋ͭ @ReactDsl open class RBuilder { val childList = mutableListOf() fun child(element: ReactElement): ReactElement { childList.add(element) return element } operator fun String.unaryPlus() { childList.add(this) } fun

child(type: Any, props: P, children: List) = child(createElement(type, props, *children.toTypedArray())) fun

child(type: Any, props: P, handler: RHandler

): ReactElement { val children = with(RElementBuilder(props)) { handler() childList } return child(type, props, children) } operator fun

RClass

.invoke(handler: RHandler

) = child(this, jsObject {}, handler) operator fun RProvider.invoke(value: T, handler: RHandler>) = child(this, jsObject { this.value = value }, handler) operator fun RConsumer.invoke(handler: RBuilder.(T) -> Unit) = child(this, jsObject> { this.children = { value -> buildElements { handler(value) } } }) {} fun

RClass

.node( props: P, children: List = emptyList() ) = child(this, clone(props), children) fun

> child(klazz: KClass, handler: RHandler

): ReactElement { val rClass = klazz.js as RClass

return rClass(handler) } inline fun

> child(noinline handler: RHandler

) = child(C::class, handler) fun

> node( klazz: KClass, props: P, children: List = emptyList() ): ReactElement { val rClass = klazz.js as RClass

return rClass.node(props, children) } inline fun

> node(props: P, children: List = emptyList()) = node(C::class, props, children) fun RProps.children() { childList.addAll(Children.toArray(children)) } } @ReactDsl open class RBuilder { val childList = mutableListOf()

Slide 99

Slide 99 text

ίʔυϦʔσΟϯά LPUMJOSFBDU 3#VJMEFSΫϥε w %0.ཁૉΛ֨ೲ͢ΔDIJME-JTUϓϩύςΟΛ࣋ͭ w DIJMEϝιουΛ࢖ͬͯཁૉΛ௥ՃͰ͖Δ @ReactDsl open class RBuilder { val childList = mutableListOf() fun child(element: ReactElement): ReactElement { childList.add(element) return element } operator fun String.unaryPlus() { childList.add(this) } fun

child(type: Any, props: P, children: List) = child(createElement(type, props, *children.toTypedArray())) fun

child(type: Any, props: P, handler: RHandler

): ReactElement { val children = with(RElementBuilder(props)) { handler() childList } return child(type, props, children) } operator fun

RClass

.invoke(handler: RHandler

) = child(this, jsObject {}, handler) operator fun RProvider.invoke(value: T, handler: RHandler>) = child(this, jsObject { this.value = value }, handler) operator fun RConsumer.invoke(handler: RBuilder.(T) -> Unit) = child(this, jsObject> { this.children = { value -> buildElements { handler(value) } } }) {} fun

RClass

.node( props: P, children: List = emptyList() ) = child(this, clone(props), children) fun

> child(klazz: KClass, handler: RHandler

): ReactElement { val rClass = klazz.js as RClass

return rClass(handler) } inline fun

> child(noinline handler: RHandler

) = child(C::class, handler) fun

> node( klazz: KClass, props: P, children: List = emptyList() ): ReactElement { val rClass = klazz.js as RClass

return rClass.node(props, children) } inline fun

> node(props: P, children: List = emptyList()) = node(C::class, props, children) fun RProps.children() { childList.addAll(Children.toArray(children)) } } fun child(element: ReactElement): ReactElement { childList.add(element) return element }

Slide 100

Slide 100 text

@ReactDsl open class RBuilder { val childList = mutableListOf() fun child(element: ReactElement): ReactElement { childList.add(element) return element } operator fun String.unaryPlus() { childList.add(this) } fun

child(type: Any, props: P, children: List) = child(createElement(type, props, *children.toTypedArray())) fun

child(type: Any, props: P, handler: RHandler

): ReactElement { val children = with(RElementBuilder(props)) { handler() childList } return child(type, props, children) } operator fun

RClass

.invoke(handler: RHandler

) = child(this, jsObject {}, handler) operator fun RProvider.invoke(value: T, handler: RHandler>) = child(this, jsObject { this.value = value }, handler) operator fun RConsumer.invoke(handler: RBuilder.(T) -> Unit) = child(this, jsObject> { this.children = { value -> buildElements { handler(value) } } }) {} fun

RClass

.node( props: P, children: List = emptyList() ) = child(this, clone(props), children) fun

> child(klazz: KClass, handler: RHandler

): ReactElement { val rClass = klazz.js as RClass

return rClass(handler) } inline fun

> child(noinline handler: RHandler

) = child(C::class, handler) fun

> node( klazz: KClass, props: P, children: List = emptyList() ): ReactElement { val rClass = klazz.js as RClass

return rClass.node(props, children) } inline fun

> node(props: P, children: List = emptyList()) = node(C::class, props, children) fun RProps.children() { childList.addAll(Children.toArray(children)) } } ίʔυϦʔσΟϯά LPUMJOSFBDU 3#VJMEFSΫϥε w %0.ཁૉΛ֨ೲ͢ΔDIJME-JTUϓϩύςΟΛ࣋ͭ w DIJMEϝιουɺଞʹͭ w 3$PNQPOFOUΛ௥Ճ w QSPQTͱࢠཁૉΛݸผͷҾ਺Ͱ௥ՃFUD fun child(type: Any, props: P, children: List): ReactElement fun child(type: Any, props: P, handler: RHandler

): ReactElement fun child(klazz: KClass, handler: RHandler

): ReactElement inline fun child(noinline handler: RHandler

): ReactElement

Slide 101

Slide 101 text

ίʔυϦʔσΟϯά LPUMJOSFBDU DSFBUF&MFNFOUϝιου w τοϓϨϕϧؔ਺ɺ3FBDUKTͷ3FBDUDSFBUF&MFNFOUͱରԠ w 3#VJMEFSDIJME-JTU3FBDU&MFNFOUʹม׵ w SFOEFSϝιουͰ࠷ऴతʹݺ͹ΕΔ external fun

createElement( type: Any, props: P, vararg child: Any? ): ReactElement

Slide 102

Slide 102 text

ίʔυϦʔσΟϯά LPUMJOSFBDU EJWϝιου w 3#VJMEFSͷ֦ுؔ਺ͱͯ͠ఆٛ w Ҿ਺CMPDLͷܕ͸3%0.#VJMEFS%*7 6OJU w CMPDLͷதͰEJW΍ͦͷଞ)UNM5BHͷϝιουΛ࠶ؼతʹهड़Ͱ͖Δʂ w )UNM5BH༻ϝιου͸શ֦ͯுؔ਺ˠ3#VJMEFS͕ͪ͝Ό͔ͭͳ͍ʂ inline fun RBuilder.div( classes: String? = null, block: RDOMBuilder
.() -> Unit ): ReactElement = tag(block) { DIV(attributesMapOf("class", classes), it) } 3%0.#VJMEFS ˠ3#VJMEFSͷࢠΫϥε EJW\ TQBO\ B\^ ^ ^

Slide 103

Slide 103 text

ίʔυϦʔσΟϯά LPUMJOSFBDU UBHϝιου w )UNM5BH༻ϝιου͔Β࣮ࡍʹݺͼग़͞ΕΔϝιου w 3#VJMEFSDIJME ϝιουΛ࣮ߦ w ,PUMJO+4Ͱಠࣗ)5.-λάΛѻ͍͍ͨʂˠUBHϝιουͰΑ͠ͳʹ inline fun RBuilder.tag( block: RDOMBuilder.() -> Unit, noinline factory: (TagConsumer) -> T ): ReactElement = child(RDOMBuilder(factory).apply { block() }.create())

Slide 104

Slide 104 text

ίʔυϦʔσΟϯά LPUMJOSFBDU ,PUMJO+4ͷίʔσΟϯά w SFOEFSϝιου͕3#VJMEFSͷ֦ுؔ਺ͱͯ͠ఆٛ ˠSFOEFSϝιουͷείʔϓ಺͸ɺUIJT͕3#VJMEFSͷΠϯελϯεͱͳΔ ˠ,PUMJOΒ͘͠)5.-ͷݟͨ໨ΛଛͳΘͳ͍ܗͰ)5.-Λॻ͚Δʂ class App : RComponent() { override fun RBuilder.render() { div { +"Hello, World!" } } } ֦ுؔ਺ϥϜμࣜͷޮՌతͳ࣮༻ྫ

Slide 105

Slide 105 text

ίʔυϦʔσΟϯά LPUMJOSFBDU ,PUMJO+4ͷίʔσΟϯά w SFOEFSϝιου͕3#VJMEFSͷ֦ுؔ਺ͱͯ͠ఆٛ ˠSFOEFSϝιουͷείʔϓ಺͸ɺUIJT͕3#VJMEFSͷΠϯελϯεͱͳΔ ˠ,PUMJOΒ͘͠)5.-ͷݟͨ໨ΛଛͳΘͳ͍ܗͰ)5.-Λॻ͚Δʂ class App : RComponent() { override fun RBuilder.render() { div { +"Hello, World!" } } } EJW\DIJME )FMMP 8PSME ^ͱಉ͡ Ͱ΋ݟͨ͜ͱͳ͍ॻ͖ํʜ

Slide 106

Slide 106 text

ίʔυϦʔσΟϯά LPUMJOSFBDU 3#VJMEFSΫϥε w 4USJOHVOBSZ1MVT ϝιου w ԋࢉࢠΦʔόʔϩʔυ ˠจࣈྻͷ୯߲ԋࢉ IPHF Λ্ॻ͖ w 3#VJMEFSΫϥεͷ಺෦Ͱએݴ ɹˠUIJT͕3#VJMEFSͷ࣌ͷΈ༗ޮ ɹɹར༻ൣғΛݶఆ͠ɺ෭࡞༻Λ཈͑Δʂ @ReactDsl open class RBuilder { val childList = mutableListOf() fun child(element: ReactElement): ReactElement { childList.add(element) return element } operator fun String.unaryPlus() { childList.add(this) } fun

child(type: Any, props: P, children: List) = child(createElement(type, props, *children.toTypedArray())) fun

child(type: Any, props: P, handler: RHandler

): ReactElement { val children = with(RElementBuilder(props)) { handler() childList } return child(type, props, children) } operator fun

RClass

.invoke(handler: RHandler

) = child(this, jsObject {}, handler) operator fun RProvider.invoke(value: T, handler: RHandler>) = child(this, jsObject { this.value = value }, handler) operator fun RConsumer.invoke(handler: RBuilder.(T) -> Unit) = child(this, jsObject> { this.children = { value -> buildElements { handler(value) } } }) {} fun

RClass

.node( props: P, children: List = emptyList() ) = child(this, clone(props), children) fun

> child(klazz: KClass, handler: RHandler

): ReactElement { val rClass = klazz.js as RClass

return rClass(handler) } inline fun

> child(noinline handler: RHandler

) = child(C::class, handler) fun

> node( klazz: KClass, props: P, children: List = emptyList() ): ReactElement { val rClass = klazz.js as RClass

return rClass.node(props, children) } inline fun

> node(props: P, children: List = emptyList()) = node(C::class, props, children) fun RProps.children() { childList.addAll(Children.toArray(children)) } } operator fun String.unaryPlus() { childList.add(this) }

Slide 107

Slide 107 text

ίʔυ୳ࡧ·ͱΊ ,PUMJO+4ͱϥούʔϥΠϒϥϦͷ࣮૷ w ,PUMJOͷݴޠ࢓༷͕ϑϧ׆༻ʂɹݴޠ࢓༷ͷ্खͳ࢖͍ํΛֶ΂Δʂ w ֦ுؔ਺ɾϥϜμࣜɾԋࢉࢠΦʔόʔϩʔυFUD w $44#VJMEFS΋ࣅͨΑ͏ͳ࣮૷ɺ೷͍ͯΈΔͱͱͯ΋ָ͍͠☺ ˠ"OESPJEɾαʔόʔαΠυͷ։ൃʹ΋׆͖Δ஌ݟΛಘΔ͜ͱ͕Ͱ͖Δʂ ,PUMJOͰϑϩϯτΤϯυͷ։ൃ͕Ͱ͖Δͷ͸ָ͍͠ʂ ୔ࢁͷਓ͕৮ͬͯ͘ΕΔͱخ͍͠☺

Slide 108

Slide 108 text

એ఻ גࣜձࣾ#FBS5BJMɹΤϯδχΞืूதʂ ͝ਗ਼ௌ͋Γ͕ͱ͏͍͟͝·ͨ͠N @@ N ˢ࠷ۙ(SBEMF͕શͯ,PUMJO%4-ʹͳͬͨ