Sass
vue.js
webpack
axios

Vue+Webpack+Sassを使ったWebアプリケーションの作り方

More than 1 year has passed since last update.

話す内容

  1. vue-routerでのルーティング
  2. APIとの通信
  3. vue-routerでのmiddleware周り

実行環境を作る

Webpackを落としてきます。

npm install -g vue-cli
vue init webpack sample
cd sample;npm install

Sassなどを入れます。

npm install --save node-sass sass-loader axios

実行します。

npm run dev

Sassを使ってみる

  1. HelloWorld.vue を開きます。
  2. templatestyle を下記のように修正します。
<template>
  <div class="hello">

    .....

    <div class="hello__footer">
      footer
    </div>
  </div>
</template>

<style scoped lang="scss">

.....

.hello {
  &__footer{
    color: #00f
  }
}
</style>

style で、lang="scss" と指定すると、Sassが使えます。


フォルダ構造

下記のようになっています。
基本的に使うのは、 src/ ディレクトリ配下です。
完全に共通して使うものは、 index.html に書きましょう。

tree -L 2
.
├── README.md
├── build
│   ├── build.js
│   ├── check-versions.js
│   ├── dev-client.js
│   ├── dev-server.js
│   ├── utils.js
│   ├── vue-loader.conf.js
│   ├── webpack.base.conf.js
│   ├── webpack.dev.conf.js
│   ├── webpack.prod.conf.js
│   └── webpack.test.conf.js
├── config
│   ├── dev.env.js
│   ├── index.js
│   ├── prod.env.js
│   └── test.env.js
├── index.html
├── node_modules
├── package-lock.json
├── package.json
├── src
│   ├── App.vue
│   ├── assets
│   ├── components
│   ├── main.js
│   └── router
├── static
└── test
    ├── e2e
    └── unit

Bootstrapの追加といらないものの削除

index.html に下記のように修正。

<!DOCTYPE html>
<html>
  <head>
    <meta charset="utf-8">
    <title>sample</title>
  </head>
  <body>
    <div id="app"></div>
    <!-- built files will be auto injected -->

    <script src="https://code.jquery.com/jquery-3.2.1.slim.min.js"></script>
    <link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.7/css/bootstrap.min.css">
    <script src="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.7/js/bootstrap.min.js"></script>
  </body>
</html>

app.vue を下記のように修正

<template>
  <div id="app">
    <router-view/>
  </div>
</template>

<script>
export default {
  name: 'app'
}
</script>

<style>
#app {}
</style>

ルーティング

router/index.js でルーティングできます。
そのまえに、src/pagessrc/pages/Home ディレクトリを作成し、 Home.vue, home.html, home.scss ファイルを追加しましょう。
そして、 下記のように実装します。

Home.vue
<template src="./home.html"></template>
<style lang="scss" src="./home.scss"></style>
<script>
  export default {}
</script>
home.html
<div class="home">
    <div class="container">
        home
    </div>
</div>

そして、 index.html を下記のように修正します。

import Vue from 'vue'
import Router from 'vue-router'
import HelloWorld from '@/components/HelloWorld'
import Home from '@/pages/Home/Home'

Vue.use(Router)

export default new Router({
  routes: [
    {
      path: '/',
      name: 'Hello',
      component: HelloWorld
    },
    {
      path: '/home',
      name: 'Home',
      component: Home
    }
  ]
})

これで、 /home のURIをルーティングできました。


APIと通信する

今回は axios を使ってリクエストを投げます。
エンドポイントは、configディレクトリ配下のファイルを修正すると良いでしょう。
productionとdevelop環境ごとに設定できます。
下記のように、リクエストを投げたいエンドポイントを書きましょう。

dev.env.js
'use strict'
const merge = require('webpack-merge')
const prodEnv = require('./prod.env')

module.exports = merge(prodEnv, {
  NODE_ENV: '"development"',
  HOME_ENDPOINT: '"http://localhost:9999/home"'
})
prod.env.js
'use strict'
module.exports = {
  NODE_ENV: '"production"',
  HOME_ENDPOINT: '"http://8.8.4.4/home"'
}

configファイルをいじった後は、dev-serverをリスタートしましょう。
再度、 npm run dev をしてください。 


次に、エンドポイントを axios を使って叩きます。
下記のように書くことで、エンドポイントからデータを取ってこれます。

<template src="./home.html"></template>
<style lang="scss" src="./home.scss"></style>
<script>
  import axios from 'axios';
  let homeEndpoint = process.env.HOME_ENDPOINT

  export default {
    created: function() {
        axios.get(homeEndpoint).then( response => {
            console.log(response)
        })
    }
  }
</script>

ボタンのクリックでイベントを発火させたい場合は、下記のように実装することでできます。

home.html
<div class="home">
    <div class="container">
        home
        <p @click="postData('id')">button</p>
    </div>
</div>
Home.vue
<template src="./home.html"></template>
<style lang="scss" src="./home.scss"></style>
<script>
  import axios from 'axios';
  let homeEndpoint = process.env.HOME_ENDPOINT
  let postEndpoint = process.env.POST_ENDPOINT

  export default {
    created: function() {
        axios.get(homeEndpoint).then( response => {
            console.log(response)
        })
    },
    methods: {
        postData: function(id) {
            axios.post(postEndpoint, {
                sendData: id
            })
        }
    }
  }
</script>

ミドルウェア

beforeEach() でフィルターできます。
上記に書いた手順で適当にログイン画面を作り、cookieを発行するようにしてください。

下記のように修正 index.jsを実装することによって、フィルターの機能ができます。

router/index.js
import Vue from 'vue'
import Router from 'vue-router'
import HelloWorld from '@/components/HelloWorld'
import Home from '@/pages/Home/Home'
import Login from '@/pages/Login/Login'
import VueCookies from 'vue-cookies'

Vue.use(Router)

let router = new Router({
  routes: [
    {
      path: '/',
      name: 'Hello',
      component: HelloWorld
    },
    {
      path: '/home',
      name: 'Home',
      component: Home
    },
    {
      path: '/login',
      name: 'Login',
      component: Login
    }
  ]
})

router.beforeEach( (to, from, next) => {
  switch (to.path) {
    case '/home':
      if( VueCookies.get('uid') == 'sampleUid' ) {
        next()
      } else {
        next('/login')
      }
      break;
    default:
      next()
      break
  }
})


export default router

また、ログインが成功した後にリダイレクトしたい場合は、this.$router.push('/home') のように記述することでリダイレクトできます。

  import VueCookies from 'vue-cookies'

  export default {
    methods: {
        login: function() {
            VueCookies.set('uid', 'sampleUid', '1y')
            this.$router.push('/home')
        }
    }
  }

まとめ

  • vuejs-templatesのwebpackめっちゃ便利
  • ガード周りもう少し綺麗に書けたら最高