Slide 1

Slide 1 text

Rails࢖͍ͷNuxt.jsೖ໳ ۜ࠲Rails#12 2019/08/29 גࣜձࣾιχοΫΨʔσϯ ࡔ઒խढ़

Slide 2

Slide 2 text

ࣗݾ঺հ • ࡔ઒խढ़ @ssh_nof • גࣜձࣾιχοΫΨʔσϯॴଐ • ޿ౡͷࣗ୐͔ΒϦϞʔτϫʔΫ • झຯɿα΢φ (໦༵͸α΢φͷ೔)

Slide 3

Slide 3 text

࿩͢͜ͱ • Rails ϓϩάϥϚͷ๻͕ Nuxt.js Ͱ։ൃ͢Δ࣌ͷྲྀΕ • ୊ࡐ͸Α͋͘ΔTODOফ͠ࠐΈॲཧ • ͍ͬͪΐ৮ͬͯΈΑ͏͔ͳͱࢥͬͯ΋Β͏ͨΊͷೖ໳ฤ

Slide 4

Slide 4 text

Nuxt.js ?

Slide 5

Slide 5 text

Nuxt.js • Vue.js ։ൃͷͨΊͷϑϨʔϜϫʔΫ • SSR (αʔόʔαΠυϨϯμϦϯά) • SPA (γϯάϧϖʔδΞϓϦέʔγϣϯ) • ଞʹ΋ϑϨʔϜϫʔΫͱͯ͠ͷ༷ʑͳػೳ͕͋Γ·͕͢ɺׂѪ ࠓճ͸ͪ͜Β

Slide 6

Slide 6 text

͓୊

Slide 7

Slide 7 text

׬੒Πϝʔδ νΣοΫϘοΫεͷΫϦοΫͰɺϦετΛ੾Γସ͑ ↓ νΣοΫϘοΫεͷΫϦοΫ ΍ͬͨ͜ͱϦετʹҠಈ

Slide 8

Slide 8 text

ϓϩδΣΫτͷ࡞੒ʙىಈ

Slide 9

Slide 9 text

ϓϩδΣΫτΛ࡞Δ w CPPUTUSBQ w WVFUJGZ w CVMNB w UFJMXJOE w FMFNFOUVJ w CVFGZ w &4-JOU࢖͏ w 1SFUUJFS࢖͏ w OQNPSZBSO ର࿩ࣜͰઃఆ npx create-nux-app ( npx :μ΢ϯϩʔυ͔Β࣮ߦ·ͰҰൃͰͰ͖ΔίϚϯυɻ࠷ۙͷ Node.js ʹ͸ೖ͍ͬͯ·͢ɻ )

Slide 10

Slide 10 text

ىಈ http://localhost:3000/ $ cd todo-list $ yarn dev ϑΝΠϧͷฤूͰࣗಈͰը໘͕੾ΓସΘΓ·͢ (ϗοτϦϩʔυ) +

Slide 11

Slide 11 text

։ൃ͢Δ

Slide 12

Slide 12 text

pugʹ͍ͭͯগ͠ ul.list-group li.list-group-item foo li.list-group-item bar • ؆ུه๏ͰHTMLΛָʹॻ͚ΔςϯϓϨʔτΤϯδϯ • Rails࢖͍ͷօ༷ʹ͸͓ͳ͡Έͷ slim ͱ΄ͱΜͲಉ͡ • yarn add —dev pug pug-plain-loader ͰΠϯετʔϧ • ࠓճHTMLͰઆ໌͢ΔͱεϥΠυͷେ͖͕͞଍Γͳ͍ͷͰ pug Λ࢖͍·͢
  • foo
  • bar

Slide 13

Slide 13 text

pagesσΟϨΫτϦʹ.vueϑΝΠϧΛ഑ஔ pages !"" index.vue #"" tasks #"" index.vue λεΫҰཡIUUQMPDBMIPTUUBTLT pages ʹϑΝΠϧΛ഑ஔ͢Ε͹ vue-router ͷ ઃఆΛࣗಈతʹ΍ͬͯ͘Ε·͢ τοϓϖʔδIUUQMPDBMIPTU

Slide 14

Slide 14 text

./pages/index.vue section.container nuxt-link(to="/tasks") λεΫҰཡ τοϓϖʔδ IUUQMPDBMIPTU • nuxt-link ίϯϙʔωϯτͰผ vue ΁ͷભҠ • ੜ੒͞ΕΔͷ͸aλάͰ͕͢ɺઌಡΈͯ͠ύϑΥʔϚϯεΛߴΊͯ͘ΕΔ

Slide 15

Slide 15 text

./pages/tasks/index.vue (λεΫҰཡશମ૾) section.container.pt-5 .row .col-6 .card .card-header ΍Δ͜ͱ ul.list-group.list-group-flush.px-3 li.list-group-item(v-for="task in unfinishedTasks" :key="task.id") input.form-check-input( :id="`task-checkbox-${task.id}`" v-model="task.finished" type="checkbox") label(:for="`task-checkbox-${task.id}`") {{ task.title }} .col-6 .card .card-header ΍ͬͨ͜ͱ ul.list-group.list-group-flush.px-3 li.list-group-item(v-for="task in finishedTasks" :key="task.id") input.form-check-input( :id="`task-checkbox-${task.id}`" v-model="task.finished" type="checkbox") label(:for="`task-checkbox-${task.id}`") {{ task.title }} export default { data() { return { tasks: [ { id: 1, title: 'ڇೕΛങ͏', finished: false }, { id: 2, title: 'ͨ·͝Λങ͏', finished: false }, ] } }, computed: { finishedTasks() { return this.tasks.filter((task) => { return task.finished }) }, unfinishedTasks() { return this.tasks.filter((task) => { return !task.finished }) } }, } IUUQMPDBMIPTUUBTLT UFNQMBUF TDSJQU ࣍ͷϖʔδͰॱʹઆ໌͠·͢ ໨ΛڽΒͯ͠ಡ·ͳͯ͘େৎ෉

Slide 16

Slide 16 text

<script> export default { data() { return { tasks: [ { id: 1, title: 'ڇೕΛങ͏', finished: false }, { id: 2, title: 'ͨ·͝Λങ͏', finished: false }, ] } }, computed: { finishedTasks() { return this.tasks.filter((task) => { return task.finished }) }, unfinishedTasks() { return this.tasks.filter((task) => { return !task.finished }) } }, } EBUB DPNQVUFE ΍ͬͨ͜ͱҰཡ pOJTIFE pOJTIFEϑϥάΛ੾Γସ͑Δ ΍Δ͜ͱҰཡ pOJTIFE

Slide 17

Slide 17 text

section.container .card .card-header ΍Δ͜ͱ ul li(v-for="task in unfinishedTasks" :key="task.id") input( :id="`task-checkbox-${task.id}`" v-model="task.finished" type="checkbox") label(:for="`task-checkbox-${task.id}`") {{ task.title }} .card .card-header ΍ͬͨ͜ͱ ul li(v-for="task in finishedTasks" :key="task.id") input( :id="`task-checkbox-${task.id}`" v-model="task.finished" type="checkbox") label(:for="`task-checkbox-${task.id}`") {{ task.title }} νΣοΫϘοΫε WNPEFMͰσʔλͱ઀ଓ λΠτϧ UBTLUJUMFΛࢀর

Slide 18

Slide 18 text

։ൃͷྲྀΕৼΓฦΓ • ϓϩδΣΫτ࡞੒ • λεΫҰཡը໘࡞੒ /pages • λεΫҰཡ෦෼ΛίϯϙʔωϯτԽ /components w શମϨΠΞ΢τ w EBUBߟ͑Δ w EBUBͷมߋํ๏ߟ͑Δ w ੔ཧ

Slide 19

Slide 19 text

/pages ͷ࢓૊Έʹ͍ͭͯ΋͏ͪΐͬͱ pages └── tasks ├── _id.vue └── _userId └── edit.vue w IUUQMPDBMIPTUUBTLT w QBHFTUBTLT@JEWVF w ͸UIJTSPVUFQBSBNTJEͰಘΒΕΔ w IUUQMPDBMIPTUUBTLTFEJU w QBHFTUBTLT@VTFS*EFEJUWVF w ϋϚΓϙΠϯτ w ಉ֊૚ʹಉ໊͡લ @JE Λ࢖͏ͱOVYUDIJMEͷѻ͍ʹͳΔ • _ ࢝·Γ͸ಈతϧʔςΟϯά • _id ͷ෦෼͸ԿͰ΋ྑ͍

Slide 20

Slide 20 text

·ͱΊ • TODOফ͠ࠐΈػೳΛNuxt.jsͰ࡞ͬͯΈͨ • pages ʹ vue ϑΝΠϧΛ഑ஔ͢Δϧʔϧ (ઃఆΑΓن໿) • ࠓճ঺հͨ͠ͷ͸΄ΜͷҰ෦ (layouts, store, middleware, …) • ͘͢͝؆୯ʹ࢝ΊΒΕΔͷͰɺࠓि຤ʹͰ΋ npx create- nuxt-app ʂ

Slide 21

Slide 21 text

λεΫҰཡΛίϯϙʔωϯτԽ͢Δ

Slide 22

Slide 22 text

section.container .card .card-header ΍Δ͜ͱ task-list(:tasks="unfinishedTasks" @check="onTaskCheck") .card .card-header ΍ͬͨ͜ͱ task-list(:tasks="finishedTasks" @check="onTaskCheck") import TaskList from '~/components/TaskList.vue' export default { components: { TaskList }, data() { return { tasks: [ { id: 1, title: 'ڇೕΛങ͏', finished: false }, { id: 2, title: 'ͨ·͝Λങ͏', finished: false }, ] } }, computed: { finishedTasks() { return this.tasks.filter((task) => { return task.finished }) }, unfinishedTasks() { return this.tasks.filter((task) => { return !task.finished }) } }, methods: { onTaskCheck(taskId) { const task = this.tasks.find(task => task.id === taskId) this.$set(task, 'finished', !task.finished) } } } ./pages/tasks/index.vue ul.list-group.list-group-flush.px-3 li.list-group-item( v-for="task in tasks" :key="task.id") input.form-check-input( :id="`task-checkbox-${task.id}`" :checked="task.finished" @change="$emit('check', task.id)" type="checkbox") label(:for="`task-checkbox-${task.id}`") |{{ task.title }} export default { props: { tasks: { type: Array, required: true } } } ./components/TaskList.vue DIFDLΠϕϯτൃՐ UBTLpOJTIFE൓స