小鳥さんとKotlinを勉強できるサイトを 100%Kotlinで作る

小鳥さんとKotlinを勉強できるサイトを 100%Kotlinで作る

IM@S Engineer Talks 2019の30分枠発表資料です

https://imas.connpass.com/event/134735/
小鳥さんの自習室: https://github.com/subroh0508/otonashi-kotlin.dev

7c3b3366947123ba6772698b09edf4e2?s=128

subroh_0508

July 06, 2019
Tweet

Transcript

  1. খௗ͞Μͱ,PUMJOΛษڧͰ͖ΔαΠτΛ ,PUMJOͰ࡞Δ ʹ͜͠Γ͞ͿΖʙ!TVCSPI@

  2. ࣗݾ঺հ w ʹ͜͠Γ͞ͿΖʙ ͱಉ͍೥  w גࣜձࣾ#FBS5BJM w "OESPJEΤϯδχΞ ,PUMJO+BWB

    ˑ w 8FCΤϯδχΞ 3BJMT3FBDU  w ୲౰଎ਫ૗ɾࡾๆ݁՚ɾਅนਸ਼ر 5XJUUFS*%!TVCSPI@ ˣ/&8 ϛϦUI෱Ԭʙ
  3. એ఻λΠϜ 0UPOBTIJ w ,PUMJO੡41"32-ΫϥΠΞϯτ w TVCSPIPUPOBTIJ ਫ୩ञ଄ʮઍත૗ʯ w ୲౰ͷ೔ຊञ w

    ළͷ৭͕߹͍͗ͯ͢ޠኮྗࣦ͏☺
  4. ໨࣍ ࡞ͬͨϞϊ঺հ w খௗ͞Μͱ,PUMJOΛֶ΂ΔαΠτʮখௗ͞Μͷࣗशࣨʯ w ੡࡞ͷϞνϕʔγϣϯ ࣮૷঺հ w αʔόʔαΠυ ,UPS

     w ϑϩϯτΤϯυ ,PUMJO+4  ·ͱΊ
  5. ͦͷલʹʜ w ,PUMJOͱ͸ w +FU#SBJOT੡ɺ੩తܕ෇͚ͷΦϒδΣΫτࢦ޲ϓϩάϥϛϯάݴޠ w +7.্Ͱಈ࡞ +BWBͱ4DBMBͷதؒʹҐஔ  w

    (PPHMF͕"OESPJEΞϓϦͷ։ൃݴޠͱͯ͠ਖ਼ࣜαϙʔτʂ w ,PUMJO+4ɾ,PUMJO/BUJWF౳ɺΫϩεϓϥοτϑΥʔϜ։ൃʹ΋ରԠ
  6. ,PUMJO͸͍͍ͧʜ Button button = …; button.setOnClickListener(new View.OnClickListener() { @Override public

    void onClick(View v) { Log.d("tag", "Clicked!") } }); ྫϘλϯΛԡ͢ͱʮ$MJDLFEʯͱදࣔ "OESPJE +BWB ˠΠϯλʔϑΣʔεఆ͕ٛ৑௕
  7. ,PUMJO͸͍͍ͧʜ val button: Button = ... button.setOnClickListener { v ->

    Log.d("tag", "Clicked!") } ྫϘλϯΛԡ͢ͱʮ$MJDLFEʯͱදࣔ "OESPJE ,PUMJO ˠ4".ม׵ ΠϯλʔϑΣʔεఆٛΛϥϜμͰॻ͚Δ
  8. ,PUMJO͸͍͍ͧʜ ྫϦετΛηϛίϩϯͰܨ͛ͯେจࣈʹม׵ ˠҾ਺MJTUͷOVMMνΣοΫ͕໘౗ɺ๨Ε͕ͪ ˠ๨ΕͨΒ࣮ߦ࣌Τϥʔ ԯͷσόΠεͰ૸ͬͯ٬ઌͰʜ String joinAndUpperCase(List<String> list) { if

    (list == null) { return ""; } return String.join(":", list).toUpperCase(); }
  9. ,PUMJO͸͍͍ͧʜ ྫϦετΛηϛίϩϯͰܨ͛ͯେจࣈʹม׵ ˠ/VMMڐ༰ɾඇڐ༰Λʮ ʯͰ໌ࣔɺڐ༰ͷ৔߹ίϯύΠϧΤϥʔ ˠʮMJTU KPJO5P4USJOH lz ʯͰ ɹɹɹʮMJTU͕OVMMͷ࣌͸KPJO5P4USJOHΛ࣮ߦ͠ͳ͍ʯ fun

    joinAndUpperCase(list: List<String>?): String { return list?.joinToString(":")?.toUpperCase() :? "" } γϯϓϧ͔࣮ͭ༻తͳจ๏Ͱʮ+BWBͭΒ͍ʯΛղܾʂɹͦΕ͕,PUMJOʂ
  10. ࡞ͬͨ΋ͷ w খௗ͞Μͷࣗशࣨখௗ͞Μͱ,PUMJOΛֶ΂ΔαΠτ w (JUIVCTVCSPIPUPOBTIJLPUMJOEFW w ػೳ w ,PUMJOͷجૅతͳจ๏ղઆ w

    8FC্Ͱখௗ͞ΜͱϖΞϓϩάϥϛϯά͠ͳ͕Β,PUMJOΛษڧͰ͖Δʂ w ,PUMJOΛษڧ͍ͨ͠খௗ͞ΜͱͷίϛϡΛָ͠ΊΔʂ
  11. 0WFSWJFX

  12. 0WFSWJFX w ,PUMJOͷ3&1-ίϯϙʔωϯτ w +FU#SBJOTLPUMJOQMBZHSPVOE w ࣗ༝ʹίʔυॻ͚Δɺ࣮ߦͰ͖Δ w ࣮श՝୊ ஬৯͍ঢ়ଶͷίʔυ

    w ग़ྗ w ඪ४ग़ྗPSίϯύΠϧΤϥʔ w +6OJUͷςετ݁Ռ
  13. 0WFSWJFX w খௗ͞Μͱͷձ࿩6* w 3&1-͔Βฤूதͷίʔυ ग़ྗΛऔಘ w αʔόʔʹ౤͛ͯ༻ҙͨ͠୆ࢺΛදࣔ w ਖ਼ղͷग़ྗʮͰ͖·ͨ͠ʂʯ

    w Τϥʔʮؒҧ͑ͪΌ͍·ͨ͠ʜʯ w ͱʹ͔͔͘Θ͍͍ʂʂʂʂʂʂʂʂ
  14. ͳͥ࡞Ζ͏ͱࢥͬͨ ,PUMJO࠷ߴʂɹ,PUMJO͔Θ͍͍ʂ ৽ن։ൃ͸,PUMJOҰ୒Ͱ͢ΑͶʔ αϯϓϧίʔυͰ͢ʔ ΄΅,PUMJO "OESPJE։ൃऀ %SPJE,BJHJ ,PUMJOϑΝʔετͰߦͧ͘!*0 ,PUMJOΊͪΌͪ͘Ό޿͕͍ͬͯΔʂˠελʔτΞοϓɾϕϯνϟʔͷੈքݶఆͰ͸

  15. ͳͥ࡞Ζ͏ͱࢥͬͨ ,PUMJO࠷ߴʂɹ,PUMJO͔Θ͍͍ʂ +BWBͰΑ͘ͳ͍ʁ ղઆຊগͳ͍Ͱ͢ΑͶʔ "OESPJE ,PUMJOॳΊͯ΍Δͱ Ͳͬͪ΋෼͔Βͳͯͭ͘Β͍ ͦΕ͸ͦ͏ Ұา౿Έग़͠੾Εͳ͍ਓʹ΋ ʮ,PUMJO࠷ߴʂʯʮ,PUMJO͔Θ͍͍ʂʯΛ஌ͬͯ΄͍͠ʂ

  16. ͳͥ࡞Ζ͏ͱࢥͬͨ ͱΓ͋͑ͣখௗ͞Μͱʮ)FMMP 8PSMEʯͯ͠Έͨ w Ṗͷ೤ҙͰશͯ,PUMJOͰ࣮૷ w ͔Θ͍͗ͨ͢ɹਓͰൃڰͨ͠ w 35͍͍Ͷ w

    1͚ͩͰͳ͘ɺ,PUMJOք۾ͷਓ͔Β΋͍͍൓Ԡ খௗ͞ΜͱͷϖΞϓϩ͠ͳ͕ΒษڧͰ͖ΔαΠτ ׂͱधཁ͕͋Γͦ͏ʂɹ͋ͱ๻͕ΊͬͪΌָ͍͠
  17. ࣮૷ղઆ w αʔόʔαΠυ w ,UPS w ϑϩϯτΤϯυ w w ,PUMJO+4

    w LPUMJOQMBZHSPVOE w SFBDISPVUFS w NBUFSJBMVJ w SFBDUTXJQFBCMFWJFXT w SFWFBMKT
  18. αʔόʔαΠυ w ,UPSܰྔɾγϯϓϧͳ8FCΞϓϦέʔγϣϯϑϨʔϜϫʔΫ w ެࣜαΠτLUPSJP w "1*αʔόʔͷ։ൃ͕؆୯ʹͰ͖Δ w 3VCZͰ͍͏TJOBUSBɺ1ZUIPOͰ͍͏qBTLతͳཱͪҐஔ w

    ௥ՃϞδϡʔϧ͕๛෋ɺඞཁͳ͚ͩ௥Ճͯ͠࢖͏ αʔόʔϩάػೳͱ͔
  19. ,UPSͰ)FMMP 8PSME w ,UPS1SPKFDU(FOFSBUPSͰϓϩδΣΫτͷεέϧτϯੜ੒ ͱΓ͋͑ͣͦͷ··#VJMEԡ͢ˠ[JQ͕߱ͬͯ͘ΔͷͰղౚ

  20. ,UPSͰ)FMMP 8PSME w "QQMJDBUJPOLUʹϧʔςΟϯάͱϨεϙϯε௥ه fun main(args: Array<String>): Unit = io.ktor.server.netty.EngineMain.main(args)

    @Suppress("unused") // Referenced in application.conf @kotlin.jvm.JvmOverloads fun Application.module(testing: Boolean = false) { routing { get("/") { call.respondText("Hello, World!”, ContentType.Text.Plain) } } } ίί
  21. ,UPSͰ)FMMP 8PSME w HSBEMFXSVOΛ࣮ߦˠMPDBMIPTUͰαʔόʔ্ཱ͕ͪΔ $ ./gradlew run Starting a Gradle

    Daemon, 1 busy and 1 stopped Daemons could not be reused, use --status for details > Task :compileKotlin … $ curl http://localhost:8080 Hello, World! ʻͰ͖·ͨ͠ʂ
  22. route("/api/v1") { @Location("/{section}/{task}/task_results") data class TaskResultsParams(val section: String, val task:

    String, val output: String, val status: String) get<TaskResultsParams> { params -> val result = TaskResultService.validate(...) call.respond(HttpStatusCode.OK, result) } @Location("/{section}/{task}/start_conversations") data class StartConversationsParams(val section: String, val task: String) get<StartConversationsParams> { params -> val conversation = CodingConversationService.build(...) call.respond(HttpStatusCode.OK, conversation) } @Location("/{section}/{task}/coding_conversations") data class CodingConversationsParams(val section: String, val task: String, val code: String?) get<CodingConversationsParams> { params -> val conversation = CodingConversationService.build(...) call.respond(HttpStatusCode.OK, conversation) } }
  23. route("/api/v1") { @Location("/{section}/{task}/task_results") data class TaskResultsParams(val section: String, val task:

    String, val output: String, val status: String) get<TaskResultsParams> { params -> val result = TaskResultService.validate(...) call.respond(HttpStatusCode.OK, result) } @Location("/{section}/{task}/start_conversations") data class StartConversationsParams(val section: String, val task: String) get<StartConversationsParams> { params -> val conversation = CodingConversationService.build(...) call.respond(HttpStatusCode.OK, conversation) } @Location("/{section}/{task}/coding_conversations") data class CodingConversationsParams(val section: String, val task: String, val code: String?) get<CodingConversationsParams> { params -> val conversation = CodingConversationService.build(...) call.respond(HttpStatusCode.OK, conversation) } } ඪ४ग़ྗͷ஋ʹର͢Δ খௗ͞Μͷฦ౴Λฦ͢"1*
  24. route("/api/v1") { @Location("/{section}/{task}/task_results") data class TaskResultsParams(val section: String, val task:

    String, val output: String, val status: String) get<TaskResultsParams> { params -> val result = TaskResultService.validate(...) call.respond(HttpStatusCode.OK, result) } @Location("/{section}/{task}/start_conversations") data class StartConversationsParams(val section: String, val task: String) get<StartConversationsParams> { params -> val conversation = CodingConversationService.build(...) call.respond(HttpStatusCode.OK, conversation) } @Location("/{section}/{task}/coding_conversations") data class CodingConversationsParams(val section: String, val task: String, val code: String?) get<CodingConversationsParams> { params -> val conversation = CodingConversationService.build(...) call.respond(HttpStatusCode.OK, conversation) } } ՝୊Λදࣔͨ͠௚ޙͷ খௗ͞Μͷฦ౴Λฦ͢"1*
  25. route("/api/v1") { @Location("/{section}/{task}/task_results") data class TaskResultsParams(val section: String, val task:

    String, val output: String, val status: String) get<TaskResultsParams> { params -> val result = TaskResultService.validate(...) call.respond(HttpStatusCode.OK, result) } @Location("/{section}/{task}/start_conversations") data class StartConversationsParams(val section: String, val task: String) get<StartConversationsParams> { params -> val conversation = CodingConversationService.build(...) call.respond(HttpStatusCode.OK, conversation) } @Location("/{section}/{task}/coding_conversations") data class CodingConversationsParams(val section: String, val task: String, val code: String?) get<CodingConversationsParams> { params -> val conversation = CodingConversationService.build(...) call.respond(HttpStatusCode.OK, conversation) } } ฤूதͷίʔυΛड͚ͯ খௗ͞ΜͷಠΓݴΛฦ͢"1*
  26. route("/api/v1") { @Location("/{section}/{task}/task_results") data class TaskResultsParams(val section: String, val task:

    String, val output: String, val status: String) get<TaskResultsParams> { params -> val result = TaskResultService.validate(...) call.respond(HttpStatusCode.OK, result) } @Location("/{section}/{task}/start_conversations") data class StartConversationsParams(val section: String, val task: String) get<StartConversationsParams> { params -> val conversation = CodingConversationService.build(...) call.respond(HttpStatusCode.OK, conversation) } @Location("/{section}/{task}/coding_conversations") data class CodingConversationsParams(val section: String, val task: String, val code: String?) get<CodingConversationsParams> { params -> val conversation = CodingConversationService.build(...) call.respond(HttpStatusCode.OK, conversation) } } ϦΫΤετύϥϝʔλʔʹର͢Δ ܕόϦσʔγϣϯΛઃఆ
  27. route("/api/v1") { @Location("/{section}/{task}/task_results") data class TaskResultsParams(val section: String, val task:

    String, val output: String, val status: String) get<TaskResultsParams> { params -> val result = TaskResultService.validate(...) call.respond(HttpStatusCode.OK, result) } @Location("/{section}/{task}/start_conversations") data class StartConversationsParams(val section: String, val task: String) get<StartConversationsParams> { params -> val conversation = CodingConversationService.build(...) call.respond(HttpStatusCode.OK, conversation) } @Location("/{section}/{task}/coding_conversations") data class CodingConversationsParams(val section: String, val task: String, val code: String?) get<CodingConversationsParams> { params -> val conversation = CodingConversationService.build(...) call.respond(HttpStatusCode.OK, conversation) } } ϞδϡʔϧΛ௥Ճ͢Δ͜ͱͰ 0CKFDUˠ+40/΁ͷϚοϐϯάΛ ͋Δఔ౓ ࣗಈԽ
  28. ϑϩϯτΤϯυ w ,PUMJO+4,PUMJOΛ+BWBTDSJQUʹτϥϯεύΠε͢ΔϑϨʔϜϫʔΫ w ඪ४ϥΠϒϥϦ w ,PUMJOˠ+4ม׵ͷ(SBEMFϓϥάΠϯ LPUMJOKT  w

    OQN΍8FCQBDLͷίϚϯυΛ(SBEMFܦ༝Ͱ࣮ߦ͢ΔϓϥάΠϯ LPUMJOGSPOUFOEQMVHJO ʻԿ΋Θ͔Βͳ͍Ͱ͢ʜ
  29. ,PUMJO+4Ͳ͏࢖͏ͷ͔ w (SBEMFʹίϯύΠϧ΍8FCQBDLͷઃఆΛهड़ɺ8FCQBDLίϚϯυ࣮ߦ w HSBEMFXCVJMEˠ,PUMJOΛ+4ʹม׵ 8FCQBDLͷόϯυϧग़ྗ w HSBEMFXSVOˠม׵ όϯυϧग़ྗ 8FCQBDLαʔόʔ্ཱͪ͛

    w ࠷ऴతͳ੒Ռ෺͕+4ϑΝΠϧʹͳΔ+4ͷϥΠϒϥϦࢿ࢈Λར༻Մ ʻ׬શʹཧղ͠·ͨ͠ʂ
  30. +BWBTDSJQU͡Όμϝͳͷʜʁ ͳͥΘ͟Θ͟,PUMJOΛ࢖͏ʁ ܕ҆શͰॻ͖͍ͨΜͰ͢ʂ ࢖͍׳Εͨ,PUMJOͰϑϩϯτ͍ͨ͠ΜͰ͢ʂ 5ZQF4DSJQUͰे෼ͩΖ͏ʁ ͋ͱ܅ɺۀ຿Ͱ3FBDU3FEVY৮͍ͬͯΔ͠ +BWBTDSJQUॻ͚ΔͩΖ͏ʁ Θ͔Δʔʔʔ ɾТɾʆ ਖ਼௚εϐʔυͱ৘ใྔॏࢹͳΒ5ZQF4DSJQU͕࠷దղͩͱࢥ͏ʜ

    ຊԻ
  31. ,PUMJO+4͡Όͳ͖ΌμϝͳΜͩ w ͔͠͠ɺখௗ͞Μͷࣗशࣨͷ৔߹ʜ w ʮ΄΅શͯ,PUMJOͰ࡞ΒΕͨ,PUMJOษڧαΠτʯͰΞϐʔϧ͠΍͍͢ʂ w ϓϩμΫγϣϯ؀ڥͰಈ࡞͢Δ,PUMJO+4ΞϓϦͷ࣮ྫʹͳΔʂ w ,PUMJO+4ͷ࣮૷͕,PUMJOͷจ๏࢓༷Λ্खʹ࢖͍ͬͯͯษڧʹͳΔʂ w

    খௗ͞Μ͕ΊͬͪΌتΜͰ͘ΕΔʂʂʂ ϞνϕʔγϣϯΛอͪ΍͍͢
  32. ϑϩϯτΤϯυͷ࣮૷ w ౔୆͸3FBDU 3FBDI3PVUFSʹΑΔ41" w 6*ϑϨʔϜϫʔΫ͸.BUFSJBM6*Λར༻ w εϫΠϓ͢Δ6*͸SFBDUTXJQFBCMFWJFXΛར༻

  33. ϑϩϯτΤϯυͷ࣮૷ w ίϛϡͷ6*͸SFWFBMKTΛར༻ w )5.- $44ͰͷεϥΠυ࡞੒ w എܠʹNQQOHΛදࣔ w ηϦϑ࿮͸ؤுͬͯ$44ͰτϨʔε

    w ࡞ͬͨεϥΠυΛJGSBNFʹຒΊࠐΜͰදࣔ
  34. ϑϩϯτΤϯυͷ࣮૷ w Ͳ͏΍ͬͯ,PUMJOͰॻ͍ͯΔͷ w 3FBDU+FU#SBJOT͕ϥούʔϥΠϒϥϦΛఏڙ LPUMJOSFBDU class App extends React.Component

    { render() { return ( <div className='title'> Welcome to React with Kotlin </div> ) } } class App : RComponent<RProps, RState>() { override fun RBuilder.render() { div("title") { +"Welcome to React with Kotlin" } } } 3FBDU ,PUMJO+4
  35. ϑϩϯτΤϯυͷ࣮૷ w ͦͷଞ!+T.PEVMFΞϊςʔγϣϯΛ࢖ͬͯ,PUMJOͷੈքʹΠϯϙʔτ w ྫSFBDUTXJQFBCMFWJFXT @JsModule("react-swipeable-views") private external val reactSwipeableViewModule:

    dynamic fun test() { reactSwipeableViewModule.default.onChangeIndex = { ... } } +4ϥΠϒϥϦΛΠϯϙʔτ PO$IBOHF*OEFYʹ ؔ਺ϦςϥϧΛ୅ೖ
  36. ϑϩϯτΤϯυͷ࣮૷ w ͦͷଞ!+T.PEVMFΞϊςʔγϣϯΛ࢖ͬͯ,PUMJOͷੈքʹΠϯϙʔτ w ྫSFBDUTXJQFBCMFWJFXT @JsModule("react-swipeable-views") private external val reactSwipeableViewModule:

    dynamic fun test() { reactSwipeableViewModule.default.onChangeIndex = { ... } } EZOBNJDܕʜʁ
  37. EZOBNJDܕͷ᠘ w EZOBNJD,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
  38. EZOBNJDܕͷ᠘ w EZOBNJD,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 KT ʜ ϝιου,PUMJOίʔυதʹੜͷ+4ίʔυΛ௚઀ॻ͚Δϝιου
  39. EZOBNJDܕͷ᠘ w EZOBNJD,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 ଘࡏ͢ΔΩʔͷ஋Λऔͬͯ͘Δ
  40. EZOBNJDܕͷ᠘ w EZOBNJD,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ʹ͍ۙจ๏Ͱ୅ೖͰ͖ͯ͠·͏
  41. EZOBNJDܕͷ᠘ w EZOBNJD,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 ΍ͩʜมͩͶ ,PUMJOΛɺ,PUMJOΛॻ͍ͯͨ͸ͣͳͷʹʜ ͍͔ͭΒ+BWBTDSJQUॻ͍ͯͨΜͩΖ͏ʜ ʜͰ΋ʜࢲʜͨͩʜࢲʜΈΜͳͱʜ
  42. EZOBNJDܕͷ᠘ w FYUFSOBMम০ࢠ,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ͷܕఆٛϑΝΠϧͱ ໾ׂ͸ಉ͡
  43. EZOBNJDܕͷ᠘ @JsModule("react-swipeable-views") private external val reactSwipeableViewModule: dynamic external interface ReactSwipeableProps

    : RProps { var index: Int var disabled: Boolean var onChangeIndex: (Int, Int, ChangeReason) -> Unit var onSwitching: (Int, String) -> Unit } fun ReactSwipeableProps.onChangeIndex(block: (Int, Int?, ReasonType?) -> Unit) { onChangeIndex = { index: Int, indexLatest: Int, reason: ChangeReason -> block(index, indexLatest, ReasonType.valueOf(reason.reason)) } }
  44. EZOBNJDܕͷ᠘ @JsModule("react-swipeable-views") private external val reactSwipeableViewModule: dynamic external interface ReactSwipeableProps

    : RProps { var index: Int var disabled: Boolean var onChangeIndex: (Int, Int, ChangeReason) -> Unit var onSwitching: (Int, String) -> Unit } fun ReactSwipeableProps.onChangeIndex(block: (Int, Int?, ReasonType?) -> Unit) { onChangeIndex = { index: Int, indexLatest: Int, reason: ChangeReason -> block(index, indexLatest, ReasonType.valueOf(reason.reason)) } } ʮPO$IBOHF*OEFYʹؔ਺ϦςϥϧΛ୅ೖʯΛ ,PUMJOͬΆ͘ॻ͚ΔΑ͏ʹ֦ͨ͠ுؔ਺
  45. .BUFSJBM6*ͱͷಆ͍ w .BUFSJBM6*Ҏ֎ͷϥΠϒϥϦ w ͦ΋ͦ΋খ͍͞ˠߦຬͨͳ͍͘Β͍ͷܕఆٛ ؔ਺ఆٛͰ0, w .BUFSJBM6* w Λ௒͑Δ6*ίϯϙʔωϯτΛ࣋ͭ

    w ܧঝؔ܎͕͋ͬͨΓɺ,PUMJO+4ͷ࣮૷Λਂ۷Βͳ͍ͱ࢖͑ͳ͔ͬͨΓ w ϥούʔϥΠϒϥϦ࡞੒ɺ࢖͑ΔΑ͏ʹˠTVCSPILPUMJONBUFSJBMVJ
  46. ͦͯ͠ʜ ,PUMJO཰ͷ,PUMJOษڧαΠτ͕஀ੜ ͡Όͳ͍ͷʜλΠτϧ࠮ٗͳͷʜ Ұ෦ϕλॻ͖ͯ͠Δ$44΍+4Λ,PUMJOͰ ੜ੒͢Ε͹ཧ࿦্ୡ੒Մೳ͔ͩΒʜ

  47. ·ͱΊ w ,PUMJO཰ʹ͍ۙ8FCαΠτΛṖͷ೤ҙͰ࡞ͬͨ w ,UPS͸͙͢ʹ৮ΕΔʂ w ,PUMJO+4͸,PUMJOʹ׳Ε͔ͯΒ৮Δͱ୔ࢁͷൃݟ͕͋Δʂ w ,PUMJO͸͘͢͝ྑ͍ݴޠ w

    ʮ+BWBͭΒ͍ʯͷଟ͘Λղফɺ։ൃऀͷੜ࢈ੑʹେ͖͘د༩ w ,PUMJO'FTU݄೔։࠵ ෼࿮$G1ఏग़ࡁ
  48. )BWFBOJDF,PUMJO XJUI,PUPSJ