俺、サービス売って家買うんだ

Swift, Kotlin, Vue.js, 統計, GCP / このペースで作ってればいつか2-3億で売れるのがポっと出来るんじゃなかろうか

【Vue.js応用】vue-routerでSPAの足回り構築

f:id:ie-kau:20150818232251p:plain

2015/10/31追記

この記事はVue.js@0.12.1を元に書かれています。最新版は1系統で書式に大きな変更がありますでのご注意ください。

Vue.jsを0.12.1から1.0.3にアップデートした際にハマったこと - 俺、サービス売って家買うんだ

さて、案件でVue.jsを使うのも手に馴染んできたのでSPA(Single Page Application)の足回りを試しに構築してみようと思います。
きっかけはこのツイート

公式ドキュメントのBuilding Larger Appsの項にも出てきており、使えそうな感じだしせっかくなので遊んでみました。

http://vuejs.org/guide/application.htmlvuejs.org

For Single Page Applications, it is recommended to use the offical vue-router library, which is now in technical preview. For more details, please refer to vue-router’s documentation.

vue-routerとは

Vue.jsオフィシャルのルータで、Vue.js 0.12.10+から利用可能です。
主な機能としては。

  • 入れ子可能なルートマッピング
  • ルーティング時にワイルドカードやクエリパラメータ
  • Modular、Components-baseのルーティング
  • HTML5 history APIで動作
  • etc

github.com

構築に必要なもの

webpack + vue-loader
Components単位で分けてそれを組み合わせて実装していきます。以前興味本位でjspmの記事を書いたけどトレンドを見てみると微妙なので今日はwebpackで。

f:id:ie-kau:20150830190854p:plain

三択ですね 笑

babel-loader
せっかく勉強なので、ES2015で書きます。

Vue.js + vue-router
Vue.jsだけだとrouter機能を持っていないのでvue-routerを使って表現します。

とりあえずサンプルを組み合わせて作ってみた

github.com

Vue.jsの開発者であるEvan Youさんが作っていた以下のサンプルを組み合わせながら簡単なSPAにしてみました。
(見た目は読んだサンプルまんまです。すいませんorz)

参考

確認したかったこと

  • ディレクトリ構成
  • routingの方法
  • urlからパラメータの受け渡し方法
  • レンダリング方法

ディレクトリ構成

ここはサンプルと少し変えて以下の様にしてみました。
(Components-baseって言われてるのにpageとか作るの微妙かな・・・)

.
├── app.vue # アプリケーション大枠(iOSアプリで言うUINavigationController)
├── components # プロダクト全体で使うコンポーネント
│   ├── a.vue
│   ├── b.vue
│   └── modal.vue # この間作ったモーダル
├── main.js
└── pages # ページ自体この中にコンポーネントを入れてページを組み上げてみた
    ├── bar.vue
    ├── foo.vue
    └── home.vue

routingの方法

一般的なWAFのrouterとほとんど同じ。
my-first-vue-router/main.js at master · hazumu/my-first-vue-router · GitHub

const Vue = require('vue')
const VueRouter = require('vue-router')

// 忘れず!
Vue.use(VueRouter)

const router = new VueRouter({
  history: true,
  saveScrollPosition: true
})

router.map({
  '/': {
    component: require('./pages/home.vue')
  },
  '/home': {
    component: require('./pages/home.vue')
  },
  '/foo': {
    component: require('./pages/foo.vue')
  },
  '/bar/:id': {
    component: require('./pages/bar.vue')
  }
})

const App = Vue.extend(require('./app.vue'))
router.start(App, '#app')

公式のサンプルではroutingのネストもできるようですね。
もはやサーバーサイドのそれと何も変わらない・・
https://github.com/vuejs/vue-router/blob/dev/example/advanced/route-config.js

// nested example
'/user/:userId': {
  component: require('./components/user/index.vue'),
  subRoutes: {
    // matches "/user/:userId/profile/:something"
    'profile/:something': {
      component: require('./components/user/profile.vue')
    },
    // matches "/user/:userId/posts"
    'posts': {
      component: require('./components/user/posts.vue')
    },
    // matches "/user/:userId/settings"
    'settings': {
      component: require('./components/user/settings.vue')
    }
  }
},

routerのオプション一部抜粋

history

  • default: false
  • history.pushState() と history.replaceState() でヒストリー管理するか?
  • デフォルト動作は#!(ハッシュバング)

saveScrollPosition

  • default: false
  • HTML5 history modeだけで動作
  • ページ遷移した時に前のページのスクロール位置を保存するかどうか

その他
http://vuejs.github.io/vue-router/options.html

urlからパラメータの受け渡し方法

this.$routeから取得できます。
my-first-vue-router/bar.vue at master · hazumu/my-first-vue-router · GitHub

  data () {
    return {
      msg: 'This is Bar!',
      id: this.$route.params.id
    }
  },

レンダリング方法

自分でcomponentsに名前を付けなくてもルートとマッチしたコンポーネントが<router-view>に表示される。

<router-view></router-view>

まとめ

よかった

  • componentsで作り、足回りさえ固まるってくるとネイティブのアプリを作ってる感じで作れる
    • この手のやつって足回りを作るのが一番時間かかる気もするけど。
  • ES2015のmoduleとVueのcomponentsの相性がいい

考え中

  • xhrのところをどうしようかな。作成者のサンプルではservice層を置いている
    • これでxhrの機能が入っちゃうとまんまAngular..
  • transition周り
    • ページ遷移のアニメーションのためのhookはありがたいけどFWレベルでは必要なのか若干懐疑的

ちょろっと入れてData-bindingで便利みたいなVue.jsでしたがここまでやるとかなりなんでもできますね。 こっそりと今後に期待してます。

(∩`ω´)⊃)) オラッオラッ

関連書籍

JavaScript フレームワーク入門

JavaScript フレームワーク入門