Upgrade to Pro
— share decks privately, control downloads, hide ads and more …
Speaker Deck
Features
Speaker Deck
PRO
Sign in
Sign up for free
Search
Search
Vue.js を初めてプロダクトに導入して直面した課題と得られた幸せ
Search
moomoo-ya
February 19, 2019
Programming
0
2k
Vue.js を初めてプロダクトに導入して直面した課題と得られた幸せ
RAKUS Meetup Tokyo #2
2019.2.19
moomoo-ya
February 19, 2019
Tweet
Share
More Decks by moomoo-ya
See All by moomoo-ya
サービスを陳腐化させない組織だった技術刷新 / Technology Renewal Initiatives
moomooya
0
1.3k
はじめてのオンラインイベント配信 with COVID-19 バグ修正版 / Online-Event-bugfixed
moomooya
0
110
一番安い子だーれだ?~黒字化のための無慈悲なタスク配分~ / Distribute tasks
moomooya
1
3k
はじめてのオンラインイベント配信 with COVID-19 バグあり版 / Online-Event-includes-bug
moomooya
0
810
やはり俺のLT登壇はまちがっている。 / my-lightning-talk-is-wrong-as-i-expected
moomooya
4
2.2k
Gatsby.jsで.md/.adocが混在できるテンプレートを作ったときの苦しみ / Pain-to-create-gatsby-template-that-supports-markdown-and-asciidoc
moomooya
0
610
LADRのすすめ&先行技術検証PRJの紹介 / Introducing-LADR-and-Technology-verification
moomooya
5
2.4k
技術書へのアクセスを劇的に向上させた話 / oreilly-safari-and-acm-membership
moomooya
2
7.4k
モノリスにおけるビジネスロジックの設計 ~アグリゲートパターン~ / aggregate-pattern-for-domain-modeling-on-monolithic
moomooya
2
1.5k
Other Decks in Programming
See All in Programming
知識0からカンファレンスやってみたらこうなった!
syossan27
5
300
파급효과: From AI to Android Development
l2hyunwoo
0
170
技術的負債と戦略的に戦わざるを得ない場合のオブザーバビリティ活用術 / Leveraging Observability When Strategically Dealing with Technical Debt
yoshiyoshifujii
0
120
事業KPIを基に価値の解像度を上げる
nealle
0
160
型安全なDrag and Dropの設計を考える
yudppp
5
410
TypeScriptのmoduleオプションを改めて整理する
bicstone
4
150
クラシルリワードにおける iOSアプリ開発の取り組み
funzin
1
500
Global Azure 2025 @ Kansai / Hyperlight
kosmosebi
0
170
JAWS DAYS 2025 re_Cheers: WEB
komakichi
0
130
VibeCoding時代のエンジニアリング
daisuketakeda
0
270
TypeScript Language Service Plugin で CSS Modules の開発体験を改善する
mizdra
PRO
2
710
Live Coding: Migrating an Application to Signals
manfredsteyer
PRO
0
130
Featured
See All Featured
Making Projects Easy
brettharned
116
6.2k
A better future with KSS
kneath
239
17k
Learning to Love Humans: Emotional Interface Design
aarron
273
40k
Practical Tips for Bootstrapping Information Extraction Pipelines
honnibal
PRO
19
1.2k
Bash Introduction
62gerente
613
210k
A designer walks into a library…
pauljervisheath
205
24k
Designing Dashboards & Data Visualisations in Web Apps
destraynor
231
53k
Visualizing Your Data: Incorporating Mongo into Loggly Infrastructure
mongodb
45
9.5k
CSS Pre-Processors: Stylus, Less & Sass
bermonpainter
357
30k
Rails Girls Zürich Keynote
gr2m
94
13k
RailsConf 2023
tenderlove
30
1.1k
The Power of CSS Pseudo Elements
geoffreycrofte
75
5.8k
Transcript
Vue.js ΛॳΊͯϓϩμΫτʹಋ ೖͯ͠໘ͨ͠՝ͱಘΒΕͨ ͤ @moomooya Isamu Suzuki, Rakus 2019.2.19
ླ ༐ʢ͖ͣ͢ ͍͞Ήʣ • ւಓग़ 35ࡀ • QiitaͰษڧձϨϙ࠷ΦδαϯΛࢦ͍ͯ͠·͢ • ओʹMicroservicesͱ͔JavaScriptؔ࿈த৺
• झຯ • ITωλͷΞφϩάήʔϜ੍࡞ • ࣾΨϯϓϥ෦෦ • ITۀքଟΊͷαόήओ࠵ @moomooya @moomoo-ya
ུྺ • ߴߍʙେֶʙ৽ଔ • ߴߍͰϓϩάϥϜίϯςετք۾Λ͏Ζ͏Ζ • IPAʢ࣌௨࢈লʣͷࢿ֨औΓ͋͞Γ • େखSIer ࣌
• ূ݊/֎ࠃҝସγεςϜͷ্ྲྀ͔ΒԼྲྀ·Ͱ • อݥਃࠐΈγεςϜͷ৽ن։ൃɺͳͲ • খنϕϯνϟʔΛܦ༝ͯ͠ϥΫε • ɹɹɹɹɹɹͷαʔϏε։࢝ • ΤϯδχΞจԽͷ͔͠ɺͳͲ • ৽نαʔϏε։ൃ ←ࠓ͜Εͷ͜ͱΛ͠·͢
ຊ
ϓϩμΫτʹ Vue.js ಋೖͯ͠ Ϳ͔ͭͬͨ՝Λڞ༗͠·͢ ະղܾ՝͋Γ·͢
1. Ξϩʔԋࢉࢠ͑ͳ͍෦͕͋Δ
ࠓ͔ΒJavaScriptॻ͘ͳΒ ES2015+ ͔ TypeScript
ؔఆٛΞϩʔԋࢉࢠ () => {}
VueίϯϙʔωϯτͰ جຊతʹΞϩʔԋࢉࢠ͑ͳ͍
͜Ε͕NG <template> <!-- ... --> </template> <script> export default {
// ... methods: { changeText: () => { this.text = "foobar"; } } } </script> VueΠϯελϯεΛࢦ͢ ͕ࢀরͰ͖ͳ͍ this
͜ΕͳΒOK <template> <!-- ... --> </template> <script> export default {
// ... methods: { changeText() { this.text = "foobar"; } } } </script> ࣍ظv3ͰͷରԠʹ ظ͠·͠ΐ͏
2. ΦϒδΣΫτͷߋ৽ํ๏
Vue.js ͱ͍͑ ϦΞΫςΟϒγεςϜ
JavaScriptΦϒδΣΫτͷߋ৽Ͱ Ϗϡʔ͕ࣗಈߋ৽͞ΕΔ
ͱͯศརɺ͘͢͝
੍ͨͩ͋͠Δ • VueΠϯελϯε͕ॳظԽ͞ΕΔͱ͖ʹ ͞ΕͨJSΦϒδΣΫτʹରͯ͠ Object.definePropertyؔͰgetter/setterΛͭ͘Δ • ͜ΕΒͷΞΫηοαΛར༻ͯ͠มߋݕΛ͢Δ
͜ΕOK <template> <!-- ༩͑ΒΕͨΦϒδΣΫτ͔Β จࣈྻग़ྗ͢Δίϯϙʔωϯτ --> <text-output v-bind:data="textObject" /> <button
v-on:click=“changeText()"> จࣈྻΛม͑Δ </button> </template> <script> export default { data() { return { textObject: { value: "ग़ྗ͢Δจࣈྻ", size: 16 } }; }, methods: { changeText() { this.textObject.value = "มߋͨ͠จࣈྻ"; } } }; </script> ॳظʹ͋ΔΛૢ࡞
͜ΕOK <template> <!-- ༩͑ΒΕͨΦϒδΣΫτ͔Β จࣈྻग़ྗ͢Δίϯϙʔωϯτ --> <text-output v-bind:data="textObject" /> <button
v-on:click=“changeText()"> จࣈྻΛม͑Δ </button> </template> <script> export default { data() { return { textObject: { value: "ग़ྗ͢Δจࣈྻ", size: 16 } }; }, methods: { changeText() { this.textObject.value = "มߋͨ͠จࣈྻ"; } } }; </script> ॳظʹ͋Δ ॻ͖͑Εը໘ʹө͞ΕΔ ॳظʹ͋ΔΛૢ࡞
͜ΕNG <template> <!-- ༩͑ΒΕͨΦϒδΣΫτ͔Β จࣈྻग़ྗ͢Δίϯϙʔωϯτ --> <text-output v-bind:data="textObject" /> <button
v-on:click=“setSize()”> αΠζΛઃఆ͢Δ </button> </template> <script> export default { data() { return { textObject: { value: "ग़ྗ͢Δจࣈྻ" } }; }, methods: { setSize() { this.textObject.size = 16; } } }; </script> ॳظʹͳ͍Λૢ࡞
͜ΕNG <template> <!-- ༩͑ΒΕͨΦϒδΣΫτ͔Β จࣈྻग़ྗ͢Δίϯϙʔωϯτ --> <text-output v-bind:data="textObject" /> <button
v-on:click=“setSize()”> αΠζΛઃఆ͢Δ </button> </template> <script> export default { data() { return { textObject: { value: "ग़ྗ͢Δจࣈྻ" } }; }, methods: { setSize() { this.textObject.size = 16; } } }; </script> ॳظʹͳ͍ Ճͯ͠มߋ͕ݕ͞Εͳ͍ ໌ࣔతʹ this.$set(this.textObject, “size”, 16); ॳظʹͳ͍Λૢ࡞
3. ཁૉ໊ͷিಥ
vueϥΠϒϥϦ͕ ͲΜͲΜඋ͞Ε͍ͯΔ
ϥΠϒϥϦͷཁૉ໊ॏෳ • ϚςϦΞϧσβΠϯͳUIϥΠϒϥϦͷVuetify • <v-image>ͱ͔<v-select>ͱ͔ͰΦγϟϨUI࡞ΕΔ • Canvasૢ࡞ϥΠϒϥϦͷKonvaΛϥοϓͨ͠vue-konva • ը૾ΦϒδΣΫτΛ<v-image>Ͱࢦఆ͢Δ
ϥΠϒϥϦͷཁૉ໊ॏෳ • ϚςϦΞϧσβΠϯͳUIϥΠϒϥϦͷVuetify • <v-image>ͱ͔<v-select>ͱ͔ͰΦγϟϨUI࡞ΕΔ • Canvasૢ࡞ϥΠϒϥϦͷKonvaΛϥοϓͨ͠vue-konva • ը૾ΦϒδΣΫτΛ<v-image>Ͱࢦఆ͢Δ
<v-image> ॏෳ
ಈ࡞͠·ͤΜͰͨ͠
ཁૉ໊ͷϧʔϧ • Vue.js ελΠϧΨΠυ https://jp.vuejs.org/v2/style-guide/index.html
͍͓ͪ͏ճආͰ͖ΔͬΆ͍ॻ͖ํ ࣌ʮผ໊Λ͚ͭΔʯΓํ͕͔Βͣ٧ΜͰ͍ͨ <script> import ComponentA from "@/components/hoge/ComponentA"; import ComponentA2 from
"@/components/fuga/ComponentA"; export default { components: { "hoge-comp-a": ComponentA, "fuga-comp-a": ComponentA2 } } </script> ಛʹ͜ͷॻ͖ํ }
4. ηΦϦʔΘ͔Βͳ͍
ϓϩμΫτͰ࡞Δͱ େྔͷ໋໊ɺϞδϡʔϧׂΛ ରॲ͠ͳ͚ΕͳΒͳ͍
camelCaseͳͷ͔ PascalCaseͳͷ͔ kebab-caseͳͷ͔
ϞδϡʔϧڥքΛ Ͳ͜ʹҾ͚͍͍ͷ͔
Vue.js υΩϡϝϯτ͕ ॆ࣮͍ͯ͠Δ
ελΠϧΨΠυ͕͋ΔͷͰ·ͣख़ಡ • Vue.js ελΠϧΨΠυʢެࣜʣ • https://jp.vuejs.org/v2/style-guide/ • Vue.js ίϯϙʔωϯτ ελΠϧΨΠυ
• https://pablohpsilva.github.io/vuejs-component- style-guide/#/japanese • ॳͪ͜ΒͷଘࡏΛΒͳ͔ͬͨͷͰۤ͠ΜͰ͍Δ
5. Vuex ͍͗͢
ηΦϦʔ͕Θ͔Βͳ͔ͬͨ݁Ռ
Vuex ʹա࣮
Vuex(Flux)ͷΞʔΩςΫνϟ https://vuex.vuejs.org/ja/
Vuexͷ࣮ηΦϦʔ • State • ঢ়ଶΛอଘ͢ΔʢάϩʔόϧͬΆ͍มྖҬʣ • ໌Β͔ʹଟ༻ͨ͠Βμϝͳงғؾ • Mutation ؔ܈
• State Λߋ৽͢Δ།Ұͷॲཧ܈ • ಉظॲཧతʹ࣮͢Δ • Action ؔ܈ • ඇಉظॲཧΛ࣮ͯ͠Α͍ • State ͷߋ৽ Mutation ܦ༝
Vuexͷ࣮ηΦϦʔ • State • ঢ়ଶΛอଘ͢ΔʢάϩʔόϧͬΆ͍มྖҬʣ • ໌Β͔ʹଟ༻ͨ͠Βμϝͳงғؾ • Mutation ؔ܈
• State Λߋ৽͢Δ།Ұͷॲཧ܈ • ಉظॲཧతʹ࣮͢Δ • Action ؔ܈ • ඇಉظॲཧΛ࣮ͯ͠Α͍ • State ͷߋ৽ Mutation ܦ༝ ←͜ΕΛ֦େղऍͯ͠͠·ͬͨ
ඇಉظσʔλऔಘॲཧΛ ͯ͢VuexͰ࣮
ઈࢍҾ͖ฦ͠த
ίϯϙʔωϯτʹด͡Δͷ ඇಉظॲཧͰίϯϙʔωϯτʹ هड़͢ΕΑ͍
6. ෆదͳmixins
Vueίϯϙʔωϯτʹ v-model ଐੑͱ͍͏ ศརͳଐੑ͕͋Γ·͢
Vue.jsͷίϯϙʔωϯτؒ௨৴ • ίϯϙʔωϯτ͔Β • v-bind:ϓϩύςΟ໊ Ͱ͢ • v-on:Πϕϯτ໊ Ͱड͚औΔ <blog-post
v-for="post in posts" v-bind:key="post.id" v-on:on-change="onChange" > </blog-post>
Vue.jsͷίϯϙʔωϯτؒ௨৴ • ࢠίϯϙʔωϯτ • props ϓϩύςΟʹఆٛͯ͠ड͚औΔ • this.$emit ͰΠϕϯτૹ৴ͯ͠ฦ͢ props:
{ key: { type: Number, default: 0 } }, methods: { onChange(value) { this.$emit("on-change", value); } }
v-modelͱ • ϓϩύςΟ໊ͱΠϕϯτ໊Λݻఆͨ͠ҥߏจ • ड͚͢ϓϩύςΟ໊Λ value • ฦ͢ΠϕϯτΛ input <blog-post
v-bind:value="post.id" v-on:input="post.id = $event.target.value" > </blog-post> <blog-post v-model="post.id"> </blog-post>
v-modelͱ • ϓϩύςΟ໊ͱΠϕϯτ໊Λݻఆͨ͠ҥߏจ • ड͚͢ϓϩύςΟ໊Λ value • ฦ͢ΠϕϯτΛ input <blog-post
v-bind:value="post.id" v-on:input="post.id = $event.target.value" > </blog-post> <blog-post v-model="post.id"> </blog-post> ͨͩ͜͠Ε ίϯϙʔωϯτͷͳ͠
v-modelରԠͳࢠίϯϙʔωϯτ • ຖճ͜ΕΛॻ͔ͳ͍ͱ͍͚ͳ͍ export default { props: { value: {
type: String, default: undefined } }, methods: { onInput(value) { this.$emit("input", value); } } }
v-modelରԠͳࢠίϯϙʔωϯτ • ຖճ͜ΕΛॻ͔ͳ͍ͱ͍͚ͳ͍ export default { props: { value: {
type: String, default: undefined } }, methods: { onInput(value) { this.$emit("input", value); } } } ϛοΫεΠϯͰ ·ͱΊͨΖ
͜͜·ͩݕূதͰ͢
propsΛmixins͢Δͷμϝͦ͏ • mixinsΛղܾ͢Δ·ͰͷҰॠvalue͕undefinedʹͳΔ • templateͰ͍ͬͯΔͱίϯιʔϧΤϥʔ͕ग़Δ • slotͱ͔͏·ͬͨ͘Βڞ௨ԽͰ͖Δ͔͠Εͳ͍ • ↑ࢼ͍ͤͯ·ͤΜ •
ੈؒͷUIϥΠϒϥϦͷιʔεΛݟͨײͩ͡ͱ ͜͜ڞ௨Խ͠ͳ͍ͷ͕ηΦϦʔͳؾ͕͍ͯ͠Δ
ͰτʔλϧͰ ಋೖͯͤ͠ʹͳ͍ͬͯ·͢
ྑ͍ͱ͜Ζαϥοͱ
1. ୯ҰϑΝΠϧίϯϙʔωϯτ
DOMͱॲཧͱελΠϧΛ·ͱΊΒΕͯૉఢ • ҙຯͷ͋Δ୯ҐͰѻ͑Δ • CSS͕ scoped Ͱ1ϑΝΠϧʹ ดͯ͡ద༻Ͱ͖Δ • ίʔυ͕ංେԽ͠ʹ͍͘
<template> <blog-post class="title" v-model="title" /> </template> <script> export default { data() { title: "λΠτϧ"; } }; </script> <style scoped> .title { font-size: large; } </style>
2. υΩϡϝϯτ͕ૉΒ͍͠
͜͜·Ͱࢀর͍ͯ͠Δ υΩϡϝϯτ ͯ͢ຊޠԽࡁΈ
தؖͳͲΞδΞݍͰྲྀߦ͍ͬͯΔΒ͍͠
ΞδΞݍͰྲྀߦ͍ͬͯΔ ϑϨʔϜϫʔΫ……͏ͬɺ಄͕ Seasar2
3. React + Flux ͷܦݧϜμʹͳΒͳ͍
Vue.js ͷঢ়ଶཧ Vuex FluxΞʔΩςΫνϟ
ʮ͔ͬͨ͜͡ͱ͕͋ΔʯఔͰ ཧղͷॿ͚ʹͳΓ·ͨ͠
·ͱΊ
ελΠϧΨΠυ͕͋ΔͷͰ·ͣख़ಡ • Vue.js ελΠϧΨΠυʢެࣜʣ • https://jp.vuejs.org/v2/style-guide/ • Vue.js ίϯϙʔωϯτ ελΠϧΨΠυ
• https://pablohpsilva.github.io/vuejs-component- style-guide/#/japanese • ॳͪ͜ΒͷଘࡏΛΒͳ͔ͬͨͷͰۤ͠ΜͰ͍Δ
͋Γ͕ͱ͏͍͟͝·ͨ͠