vue + vuex + vue-router のwebpackなしサンプル(コピペでできる)
問題
webpackとかLaravelなしで vue+vuex+vue-routerできないですか。
答え
htmlファイル1個と、jsファイル1個で、小さなSPA(Single Page Application)っぽいことをしてみる。
ファイル構成は以下のみ。
. |-- index.html `-- app.js
vue, vuex, vue-router はCDNから読み込めばOK(もちろんローカルにダウンロードして使ってもOK)。
jsはhtmlの中に <script>~</script> で書いても構わないけど、一応分けた。
HTML(index.html)
SPAでよく見る <div id=”app”></div> しかないHTML。
<!DOCTYPE html> <html lang="ja"> <head> <meta charset="utf-8"> <meta name="viewport" content="width=device-width, initial-scale=1"> <title>vue + vue-router + vuex</title> <link rel="stylesheet" href="https://stackpath.bootstrapcdn.com/bootstrap/4.4.1/css/bootstrap.min.css"> <script src="https://cdn.jsdelivr.net/npm/vue"></script> <script src="https://unpkg.com/vuex"></script> <script src="https://unpkg.com/vue-router/dist/vue-router.js"></script> <script src="https://cdn.jsdelivr.net/npm/es6-promise@4/dist/es6-promise.auto.js"></script> <script defer src="app.js"></script> </head> <body> <div id="app"></div> </body> </html>
スタイルシートはBootstrap4を入れた。
自前のCSSファイルがあれば追加で読み込んでよい。
es6-promise.auto.js はIE対策。Promiseのないブラウザ対策。不要なら削除してもよい。
JavaScript(app.js)
1つのファイルにすべてを書く。
- vue-routerに呼び出してもらうコンポーネント定義(Home、Foo、Bar)
- ルート定義(route)
- VueRouter作成(router)
- Vuexのストア作成(store)
- Appとヘッダー(Navigation)、フッター(Footer)の子コンポーネント作成
- 最後に new Vue({el: ‘#app’})
- Vueにstoreとrouterを持たせることで、子コンポーネントたちも this.$store で参照できる
const Home ={ template: '<div>Homeです。</div>' } const Foo ={ template: '<div><p>Foo画面です</p>' + '<button class="btn btn-info" v-on:click="$store.commit(\'increment\')">クリックするとカウンターが増えます {{ count }}回目</button></div>', computed: { count: function () { return this.$store.state.count } } } const Bar ={ template: '<div><p>Bar画面です</p>' + '<button class="btn btn-success" v-on:click="$store.commit(\'increment\')">クリックするとカウンターが増えます {{ count }}回目</button></div>', computed: { count: function () { return this.$store.state.count } } } const routes = [ { path: '/', component: Home }, { path: '/foo', component: Foo }, { path: '/bar', component: Bar } ] const router = new VueRouter({ routes: routes }) const store = new Vuex.Store({ state: { count: 0 }, mutations: { increment(state) { state.count++ } } }); const Navigation ={ template: '<nav class="nav bg-light mb-3">' + '<router-link to="/" class="nav-link">Home</router-link>' + '<router-link to="/foo" class="nav-link">Foo</router-link>' + '<router-link to="/bar" class="nav-link">Bar</router-link>' + '</nav>' } const Footer ={ template: '<footer class="fixed-bottom bg-light p-3">フッター</footer>', } const App ={ template: '<div><Navigation/><div class="container-fluid"><router-view/></div><Footer/></div>', components: { Navigation: Navigation, Footer: Footer }, computed: { count () { return this.$store.state.count } } } new Vue({ el: '#app', router: router, store: store, template: '<App/>', components: { App: App } });
ES6では以下のように短縮して書かれていることが多いですが、
components: { Navigation, Footer },
JSONっぽいこちらの書き方で書いてます。
components: { Navigation: Navigation, Footer: Footer },
結果
ちゃんとちょっとしたSPAらしい動きをする。
次は
node.js、npm、composer、Laravelなどに一切触れなくてもここまではできました。
こうしてみると課題が見えてきます。
- テンプレートが書きにくい
- このまま1ファイルに書き続けるのはつらい
- 大規模なものになると必要に応じてコンポーネントを遅延ロードする仕組みにしたくなる
結局webpack導入となるわけですね。
コメント