Upgrade to Pro — share decks privately, control downloads, hide ads and more …

vuejs-meetup

kazupon
January 29, 2015

 vuejs-meetup

Railsで作られたサービスにVue.jsを導入したというお話

kazupon

January 29, 2015
Tweet

More Decks by kazupon

Other Decks in Programming

Transcript

  1. About Me • @kazupon • ॴଐɿCUUSOO SYSTEM • ໾ׂɿϦʔυΤϯδχΞ •

    ࢓ࣄɿ
 ϑϩϯτΤϯυɺόοΫΤϯυɺΠϯϑϥɺͳͲɺγεςϜ શൠɺ΄΅ϑϧελοΫʂ • ࡞ͬͨVue.jsͷPluginɿ
 vue-i18n: https://github.com/kazupon/vue-i18n
 vue-validator: https://github.com/kazupon/vue-validator
  2. 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>
  3. 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); });
  4. 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) { ... } } });
  5. 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>
  6. ૄ݁߹ͳ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͠ ͯɺ਌ଆͰ࡟আͯ͠΋Β͏
  7. Template • View ʹ૬౰͢Δ Template(html) ΋ɺrequire Ͱ͖Δ Α͏ɺͳΔ΂͘ϑΝΠϧͱͯ͠؅ཧ # Tempalte

    <div class=“widget”> ... <div v-component="modal" v-ref="modal"></div> ... </div>
  8. Filter • Filter΋ViewModelͷ࣌ͱಉ ༷ɺ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; }, … } });
  9. 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); }
  10. 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
  11. Ϟδϡʔϧ؅ཧํ๏ • Vue.jsͰॻ͍ͨ΋ͷར ༻͢Δ΋ͷ͸ɺapp/ assets/javascriptsͱ͸ ผʹઐ༻σΟϨΫτϦ Λ࡞ͬͯͦ͜ͷதͰ؅ ཧ . !""

    Capfile !"" Gemfile !"" Gemfile.lock !"" README.md !"" Rakefile !"" app !"" config !"" config.ru !"" db !"" frontend !"" lib !"" log !"" public !"" script !"" spec #"" vendor ͜ͷσΟϨΫτϦ Ͱ؅ཧ
  12. Ϟδϡʔϧߏ଄ • ಠࣗن໿Ͱߏ଄Խ • ԼهͷΑ͏ʹɺVue.jsͰॻ͍ͨ Ϟδϡʔϧ͚ͩͰͳ͘ɺଞͷ Ϟδϡʔϧ΋Ұॹʹ؅ཧ
 - ڞ௨ϥΠϒϥϦ
 -

    UIؔ࿈
 - APIΫϥΠΞϯτ
 - ଟݴޠϦιʔε
 . !"" Makefile !"" gulpfile.js !"" index.js !"" lib $ !"" api $ ... $ !"" utils.js $ !"" validates.js $ #"" widgets !"" locales $ !"" en.json $ #"" ja.json #"" package.json
  13. ϞδϡʔϧͷϏϧυ • 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 ...
  14. ϨΨγʔίʔυ΁ͷ૊ΈࠐΈ • 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 }); })();