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
vuejs-meetup
Search
Sponsored
·
Ship Features Fearlessly
Turn features on and off without deploys. Used by thousands of Ruby developers.
→
kazupon
January 29, 2015
Programming
16
8.4k
vuejs-meetup
Railsで作られたサービスにVue.jsを導入したというお話
kazupon
January 29, 2015
Tweet
Share
More Decks by kazupon
See All by kazupon
Oxlint JS plugins
kazupon
1
1.1k
gunshi
kazupon
1
170
Nitro v3
kazupon
2
440
わたしのOSS活動
kazupon
3
590
Vapor Revolution
kazupon
3
4k
Vue.js最新動向
kazupon
3
1.6k
Vue 3.4
kazupon
13
4.8k
Vue & Vite Rustify
kazupon
4
2.4k
Vue.jsエコシステム動向2023
kazupon
17
9k
Other Decks in Programming
See All in Programming
AI活用のコスパを最大化する方法
ochtum
0
120
TROCCOで実現するkintone+BigQueryによるオペレーション改善
ssxota
0
110
AIとペアプロして処理時間を97%削減した話 #pyconshizu
kashewnuts
1
170
Railsの気持ちを考えながらコントローラとビューを整頓する/tidying-rails-controllers-and-views-as-rails-think
moro
4
360
エージェント開発初心者の僕がエージェントを作った話と今後やりたいこと
thasu0123
0
220
要求定義・仕様記述・設計・検証の手引き - 理論から学ぶ明確で統一された成果物定義
orgachem
PRO
1
500
Go1.26 go fixをプロダクトに適用して困ったこと
kurakura0916
0
310
NOT A HOTEL - 建築や人と融合し、自由を創り出すソフトウェア
not_a_hokuts
2
490
Go 1.26でのsliceのメモリアロケーション最適化 / Go 1.26 リリースパーティ #go126party
mazrean
1
310
go directiveを最新にしすぎないで欲しい話──あるいは、Go 1.26からgo mod initで作られるgo directiveの値が変わる話 / Go 1.26 リリースパーティ
arthur1
2
410
AI時代のソフトウェア開発でも「人が仕様を書く」から始めよう-医療IT現場での実践とこれから
koukimiura
0
110
izumin5210のプロポーザルのネタ探し #tskaigi_msup
izumin5210
1
500
Featured
See All Featured
Optimising Largest Contentful Paint
csswizardry
37
3.6k
Speed Design
sergeychernyshev
33
1.6k
How to optimise 3,500 product descriptions for ecommerce in one day using ChatGPT
katarinadahlin
PRO
1
3.5k
Skip the Path - Find Your Career Trail
mkilby
0
71
Designing for Performance
lara
611
70k
[Rails World 2023 - Day 1 Closing Keynote] - The Magic of Rails
eileencodes
38
2.8k
Technical Leadership for Architectural Decision Making
baasie
2
270
Imperfection Machines: The Place of Print at Facebook
scottboms
269
14k
Agile Leadership in an Agile Organization
kimpetersen
PRO
0
96
The Illustrated Guide to Node.js - THAT Conference 2024
reverentgeek
1
280
Exploring the Power of Turbo Streams & Action Cable | RailsConf2023
kevinliebholz
37
6.3k
Java REST API Framework Comparison - PWX 2021
mraible
34
9.2k
Transcript
RailsͰ࡞ΒΕͨαʔϏεʹ Vue.jsΛಋೖͨ͠ͱ͍͏͓ Vue.js Meetup 2015-01-28 @kazupon
About Me • @kazupon • ॴଐɿCUUSOO SYSTEM • ׂɿϦʔυΤϯδχΞ •
ࣄɿ ϑϩϯτΤϯυɺόοΫΤϯυɺΠϯϑϥɺͳͲɺγεςϜ શൠɺ΄΅ϑϧελοΫʂ • ࡞ͬͨVue.jsͷPluginɿ vue-i18n: https://github.com/kazupon/vue-i18n vue-validator: https://github.com/kazupon/vue-validator
Vue.jsΛ͍ͬͯΔฐࣾαʔϏε
Vue.jsಋೖલͷΞʔΩςΫνϟ αʔό ΫϥΠΞϯτ
• αʔόαΠυͰHTMLΛϨϯμϦϯά͢Δయܕతͳ ϖʔδભҠͷΞϓϦέγϣϯ • UX͕ٻΊΒΕΔ෦ɺjQueryͷϓϥάΠϯɺAjax ͳͲͰରԠ • JavascriptɺCSS Rails
ͷ Sprockets ʹ͓·͔ͤ
͔͠͠ɺ͕ɻɻɻ
Կ͕ͳͷ͔ • ΫϥΠΞϯταΠυಛʹ MVC ͳͲͷΞϓϦέʔ γϣϯΞʔΩςΫνϟ͕ͳ͘ɺยखؒΦϨΦϨΞʔ ΩςΫνϟͰΧΦεʹͳ͍ͬͯΔ • ഭΓདྷΔϏδωεཁ݅ͰɺUI/UXվળʹΑΔߴͳ UIΛཁٻ͢Δ࣮͕૿͖͑ͯͯɺϝϯς͕ͭΒͨ
Μɻɻɻ
Rails & data-*Λͬͨ ΦϨΦϨController # Javascript $(document).ready(function () { var
module = constantnize($(‘body’).data(‘controller-name’)); if (module) { module.init(); } }); # HTML template <html> ... <body data-controller-name=“<%= contoller.controller_name %>”>...</doby> ... </html>
jQueryΠϕϯτϋϯυϥ & DOMૢ࡞ͷཛྷ $('body .projects').on('focus', 'textarea', function () { var
value = $(this).val().split(‘\n’); var value_row = 0; $.each(value, function(i, val) { value_row += Math.max(Math.ceil(val.length / self.cols), 1); }); var input_row = $(this).attr('rows'); var original_row = $(this).data('default_row'); var next_row = (input_row <= value_row) ? value_row + 0 : Math.max(value_row + 1, original_row); $(this).attr('rows', next_row); });
͜ͷ··ͰϠόΠʂ Ϋιίʔυ͕૿͑Δ͔Γʂʂ
͜ΕҎ্ϠόΫͳΒͳ͍Α͏Α͏ Կͱ͔ͤͶʂ
ͱ͏͍͏Θ͚ͰVue.jsΛಋೖ http://vuejs.org
ͳͥɺVue.jsΛಋೖͨ͠ͷ͔ʁ
લఏ݅ • طଘͷjQueryͰॻ͔Εͨίʔυࢿ࢈Λ׆༻Ͱ͖Δ͜ͱ • ݱঢ়ͷΞϓϦέʔγϣϯʹରͯ͠ΈࠐΈ༰қͰɺط ଘ࣮ʹରͯ͠෭࡞༻͕΄ͱΜͲͳ͍͜ͱ • ίϩίϩUI༷͕มΘΔϏδωεཁ݅ʹରͯ͠ɺ͜Ε ·ͰͲ͓Γɺ։ൃεϐʔυΛҡ࣋Ͱ͖Δ͜ͱ •
ଞͷϓϩδΣΫτར༻ՄೳͰ͋Δ͜ͱ • ͙͢ʹ͑Δ͜ͱ
ͱ͍͏Θ͚ͰҎԼΛݕ౼
Vue.jsΛಋೖͨ͠ཧ༝ • ଞͷϥΠϒϥϦͱׯব͕΄ͱΜͲͳ͍ • σʔλόΠϯσΟϯάͰɺੜDOMૢ࡞ͷ࣮Λͦ ΜͳʹΨϦΨϦॻ͔ͣͱɺUIͷදࣔɾৼ͍Λָ ʹ࣮Ͱ͖Δ • CommonJS ϕʔεͰϞδϡʔϧԽͰ͖Δ
• ֶशίετ͕͍
Vue.jsΛಋೖͨ͠ݱঢ়
ViewModel • Vue.jsͷWebαΠτʹॻ͍ͯ͋ Δͱ͓ΓɺVue.jsͷϞδϡʔϧ ͱͯ͠ར༻Ͱ͖ΔΑ͏ɺ Vue.extendͰαϒΫϥεԽ͠ ͯɺmodule.exports ͢Δ component system:
http://vuejs.org/guide/components.html var Modal = module.exports = Vue.extend({ template: require('./modal.html'), components: { ... }, data: function () { return { title: '', ... } }, methods: { show: function () { ... }, hide: function () { ... }, onClickClose: function (e) { ... } } });
ViewModelͷొ • Vue.extendͰϞδϡʔϧԽ͠ ͨͷɺVue.component Ͱ άϩʔόϧొͤͣɺɺ ඞཁͳͱ͖ʹ require ͯ͠ componentsΦϓγϣϯͰࢦఆ
• ޙ v-component ɺv-ref Ͱ ΨγΨγ͏ # ViewModel var Widget = module.exports = Vue.extend({ template: require('./widget.html'), ... components: { modal: require('../modal') }, ... methods: { onClickOpenModal: function () { this.$.modal.show(); }, ... } }); # View <div class=“widget”> ... <div v-component="modal" v-ref="modal"></div> ... </div>
ૄ݁߹ͳViewModel • TODOϦετͷΑ͏ͳɺࢠؔ ͕͋ΔViewModelΛ࡞͢ Δ߹ɺΠϕϯτAPIΛۦ • Πϕϯτ໊conflict͕ى͖ͳ ͍Α͏namespaceΛར༻ • v0.11.4Ͱɺv-eventsΛ͑
ɺࢠଆͰ$emitͰൃՐͨ͠Π ϕϯτर͑·͢ … events: { ‘ChildWidget:remove’: function (vm, index) { // remove the item from the item collection // … }) } … onClickRemoveItem: function (event, index) { this.$dispatch( ‘ChildWidget:remove’, event.targetVM, index ); }) onClickRemoveItem: function (event, index) { this.$dispatch( ‘ChildWidget:remove’, event.targetVM, index ); }) ࢠ1 ࢠx ϢʔβʔͷΠϯλ ϥΫγϣϯʹΑͬͯ আཁٻ͕དྷͨΒɺΠϕϯτΛdispatch͠ ͯɺଆͰআͯ͠Β͏
Template • View ʹ૬͢Δ Template(html) ɺrequire Ͱ͖Δ Α͏ɺͳΔ͘ϑΝΠϧͱͯ͠ཧ # Tempalte
<div class=“widget”> ... <div v-component="modal" v-ref="modal"></div> ... </div>
Filter • FilterViewModelͷ࣌ͱಉ ༷ɺmodule.exportsͯ͠ɺ requireͰ͖ΔΑ͏ʹ͍ͯ͠Δ • FilterΛొ͢Δͱ͖ɺ ComponentԽͨ͠ViewModel ͷͱ͖ͱಉ༷ɺVue.filterͰά ϩʔόϧొͤͣɺඞཁͳͱ
͖ʹrequireͯ͠ɺfiltersΦϓ γϣϯʹࢦఆ͍ͯ͠Δ # Filter module module.exports = { required: function required (val) { return !val ? false : true; }, ... }; # ViewModel var filters = require(‘./filters’); var Invitation = module.exports = Vue.extend({ template: require('./invitaion'), ... filters: { validateRequired: function (val) { this.validation.email = filters.required(val); return val; }, … } });
Resource • ಛʹpluginతͳͷΛ͏͜ͱ ͳ͘ɺϥΠϒϥϦ(superagent) ΛͬͯɺWebAPIͷend-point ʹϦΫΤετ͢Δ͜ͱͰ resourceʹΞΫηε superagent: http://visionmedia.github.io/superagent/ var
request = require('superagent-browserify'); module.exports = list; function list (params, fn) { params = params || {}; var endPoint = ‘/api/v1/xxx’; // ... request .get(endPoint) .query(params) .withCredentials() .end(fn); }
Plugin • vue-i18n: ࠃࡍԽରԠ • αʔόଆͰ cookie ʹઃఆͨ͠ locale ใΛऔಘͯ͠ɺදࣔॲཧ
͢Δݴޠͷઃఆ • v-t ·ͨ Vue.t Ͱ Rails ͷ i18n like ʹ key Λࢦఆͯ͠ར༻ # Entrypoint var cookie = require('cookie-cutter'); var Vue = require('vue'); var i18n = require('vue-i18n'); // locale setting var locale = cookie.get('locale') || ‘en’; Vue.use(i18n, { lang: locale, locales: { en: require('./locales/en.json'), ja: require('./locales/ja.json') } }); # Tempalte <div> <p v-t=“foo.bar"></p> </div> vue-i18n: https://github.com/kazupon/vue-i18n
Ϟδϡʔϧཧํ๏ • Vue.jsͰॻ͍ͨͷར ༻͢Δͷɺapp/ assets/javascriptsͱ ผʹઐ༻σΟϨΫτϦ Λ࡞ͬͯͦ͜ͷதͰ ཧ . !""
Capfile !"" Gemfile !"" Gemfile.lock !"" README.md !"" Rakefile !"" app !"" config !"" config.ru !"" db !"" frontend !"" lib !"" log !"" public !"" script !"" spec #"" vendor ͜ͷσΟϨΫτϦ Ͱཧ
Ϟδϡʔϧߏ • ಠࣗنͰߏԽ • ԼهͷΑ͏ʹɺVue.jsͰॻ͍ͨ Ϟδϡʔϧ͚ͩͰͳ͘ɺଞͷ ϞδϡʔϧҰॹʹཧ - ڞ௨ϥΠϒϥϦ -
UIؔ࿈ - APIΫϥΠΞϯτ - ଟݴޠϦιʔε . !"" Makefile !"" gulpfile.js !"" index.js !"" lib $ !"" api $ ... $ !"" utils.js $ !"" validates.js $ #"" widgets !"" locales $ !"" en.json $ #"" ja.json #"" package.json
ϞδϡʔϧͷϏϧυ • Gulp + BrowserifyͰϞδϡʔ ϧԽͨ͠JSίʔυ܊ͨͪΛɺ ·ΔͬͱϏϧυͯ͠όϯυϧ • ϏϧυʹΑΓόϯυϧͨ͠JS ϑΝΠϧΛɺapp/assets/
javascripts ʹஔͤͯ͞ɺ application.jsͰrequireͤ͞Δ • ࠷ऴతʹSprocketsͰ·͔ͤΔ . !"" app $ !"" assets $ $ !"" images $ $ !"" javascripts $ $ $ !"" application.js $ $ $ !"" bundle.js $ $ $ ... $ $ $ #"" zzz.js $ $ #"" stylesheets !"" frontend $ !"" Makefile $ !"" gulpfile.js $ !"" index.js $ !"" lib $ $ !"" api $ $ ... $ $ !"" utils.js $ $ !"" validates.js $ $ #"" widgets $ !"" locales $ $ !"" en.json $ $ #"" ja.json $ #"" package.json ...
ϨΨγʔίʔυͷΈࠐΈ • RailsͷControllerͰϨϯμϦ ϯά͞ΕΔςϯϓϨʔτϑΝ ΠϧʹscriptλάͰɺrequire Ͱ·Δͬͱ࣮ͨ͠ ViewModelΛҾ͖ࠐΜͰɺ ΠϯελϯεԽ͢Δ͚ͩ • ॳظσʔλ͕ඞཁͳΒɺ
JSONΛϨϯμϦϯάͯ͠ dataʹηοτ # erb template ... <div id="widgets" v-cloak v-repeat="item: items" v-component="widget-item"></div> ... <script> (function () { var Widget = require('bundle').Widget; var data = JSON.parse('<%= j(object.to_json).html_safe %>'); new Widget({ el: '#widgets', data: data }); })();
Vue.jsΛಋೖͨ݁͠Ռ • ࣮ͨ͠ComponentΛɺ؆୯ʹ ͍·ΘΓͨ͠Γɺ֦ுͨ͠Γ͢Δ ͜ͱ͕Ͱ͖ΔΑ͏ʹͳͬͨ - ։ൃੜ࢈ੑ্ - ϝϯςφϯεੑ্ Vue.jsͰ࣮ͨ͠
Component
Vue.jsΛಋೖͨ݁͠Ռ • ଞͷϓϩδΣΫτͰɺϥΠϒϥϦײ֮Ͱɺ ComponentΛҾ͖ࠐΜͰར༻Ͱ͖ΔΑ͏ͳͬͨ - Ϟδϡʔϧੑ্ Vue.jsͰ࣮ͨ͠ ComponentΛ֦ு
·ͱΊ • jQueryͷΫιίʔυ͕૿৩͢ΔΧΦεͳΫϥΠΞϯτ αΠυ • զʑͷχʔζʹ͋ͬͨVue.jsΛ࠾༻͢Δ͜ͱͰɺΫϥ ΠΞϯταΠυΛߏԽ • ϨΨγʔίʔυΛ͋·Γमਖ਼͢Δ͜ͱͳ͘ΈࠐΊΔ ͜ͱ͕Ͱ͖ɺ͔ͭଞͷϓϩδΣΫτͰར༻Մೳ
• ͜Ε·ͰͲ͓Γ։ൃεϐʔυΛҡ࣋ͭͭ͠ɺΧΦεͩͬ ͨੈքΛվળ͢Δ͜ͱ͕Ͱ͖ͨ
͓·͚
Vue.jsʹର͢Δෆຬ • UIͷঢ়ଶͱModelͷ͕ͬͪ͝Όʹͳ͍ͬͯΔɺ $data Λ͍ͨ͠ • αʔόαΠυͰ Vue.render Έ͍ͨͷͰɺಈ͔ ͯ͠ϨϯμϦϯά͍ͨ͠
͝੩ௌ ͋Γ͕ͱ͏͍͟͝·ͨ͠ʂ