【Vue】mixin / directives / filters / Vue Routerについてまとめてみたよ

# Vueまとめ３(上級編)

こちらの記事は、Adnan Babakan 氏によりDev.to上で公開された『 Vue cheat sheet 3 』の邦訳版です（原著者から許可を得た上での公開です）

- 元記事：[Vue cheat sheet 3 (advanced)](https://dev.to/adnanbabakan/vue-cheat-sheet-1-194a)

原著をベースに説明の足りない部分は適宜、追記しています。
（追記・改変の許可は得ています。）

---

![Cover image for Vue cheat sheet 3 (advanced)](https://res.cloudinary.com/practicaldev/image/fetch/s--7EE7vwoj--/c_imagga_scale,f_auto,fl_progressive,h_420,q_auto,w_1000/https://thepracticaldev.s3.amazonaws.com/i/zqza2ik0udizmehpvpzv.png)

DEV.toコミュニティの皆さん、こんにちは！

Vueまとめシリーズは多くの注目を集めたので、シリーズの公開を続けることにしました。これは、ほとんどすべての主要な初心者向けの事柄が以前のものでカバーされているので、これは少し高度になっています。

いくつかのコードサンプルは公式ウェブサイトから引用しています。[Vue.js](https://vuejs.org/guide/)で確認できます。[^1]

[^1]: 日本語版は[こちら](https://jp.vuejs.org/guide/)を参照

<!-- 
 [](#table-of-content)Table of content
=====================================

*   [Mixins](#mixins)
    *   [Mixin option merging](#mixin-option-merging)
    *   [Global mixins](#global-mixins)
*   [Custom directives](#custom-directives)
    *   [Custom global directives](#custom-global-directives)
*   [Filters](#filters)
    *   [Global filters](#global-filters)
*   [Router](#router)
    *   [Getting started with router](#getting-started-with-router)
        *   [Router installation](#router-installation)
        *   [Defining routes](#defining-routes)
    *   [Router links](#router-links)
    *   [Advanced routing](#advanced-routing)
        *   [Dynamic routes](#dynamic-routes)
            *   [Reacting to dynamic routes param changes](#reacting-to-dynamic-routes-param-changes)
        *   [404 route](#404-route)
        *   [Asterisk routes](#asterisk-routes)
    *   [Named routes](#named-routes)
        *   [Named routes with params](#named-routes-with-params)
    *   [Programmatic navigation](#programmatic-navigation)
        *   [Programmatic named navigation](#programmatic-named-navigation)
        *   [Programmatic navigation with params](#programmatic-navigation-with-params)
    *   [Route redirection](#route-redirection)
        *   [Route named redirection](#route-named-redirection)
        *   [Dynamic route redirection](#dynamic-route-redirection)
        *   [Route redirection with params](#route-redirection-with-params)
    *   [Route alias](#route-alias)
-->

## `mixins` - ミックスイン

簡単に言うと、ミックスインは別々のファイルに保存されるコンポーネントの一部であり、他のコンポーネントで再使用可能なもの。

ミックスインは次のよう書くことができる。

```javascript
// define a mixin object
export const myMixin = {
  created: function () {
    this.hello()
  },

  methods: {
    hello: function () {
      console.log('Hello from mixin!')
    }
  }
}
```

ご覧のとおり、これには`created`フックと`hello`というメソッドがあるので、このmixinを次のようにコンポーネントで使うことができる。

```vue
    <script>
        import { myMixin } from './myMixin.js'

        export default {
            mixins: [myMixin]
        }
    </script>
``` 

したがって、このコンポーネントでこれらのフックとメソッドを記述した場合と同様に機能する。

### ミックスインが競合した場合

コンポーネント自身のプロパティまたはメソッドとミックスインの間に競合がある場合は、ミックスインではなくコンポーネントの方が優先される。

```javascript
    let mixin = {
      data: function () {
        return {
          message: 'hello',
          foo: 'abc'
        }
      }
    }

    new Vue({
      mixins: [mixin],

      data: function () {
        return {
          message: 'goodbye',
          bar: 'def'
        }
      },

      created: function () {
        console.log(this.$data)
        // ミックスインではなくコンポーネントのdataになっている
        // => { message: "goodbye", foo: "abc", bar: "def" }
      }
    })
```    

Vueによる上書きの処理方法は変更できるが、それについては別の記事で説明する。

### `Vue.mixin()` - グローバルミックスイン

グローバルミックスインは、作成されたすべてのVueインスタンスをスコープに含むという以外は通常のミックスインと同様の機能を提供する。

```javascript

import Vue from 'vue'

Vue.mixin({
    methods: {
        sayHi() {
            alert('Salam!')
        }
    }
});

const app = new Vue({
    el: '#app'
})
```    

このメソッド`sayHi`は、上記のコードのすべてのコンポーネントとVueインスタンスで使用できる。

## `directives` - カスタムディレクティブ

ご存じのとおり、ディレクティブはVueがDOMを処理する方法だ。たとえば、`v-model`や`v-show`はディレクティブだ。

ディレクティブを定義するには、次のようにする。

```vue
<script>
export default {
    directives: {
        focus: {
            inserted: function (el) {
                el.focus()
            }
        }
    }
}
</script>
```

focusディレクティブは、`v-focus`として次のように使うことができるようになる。

```vue
// コンポーネントがレンダリングされるとすぐにinput要素がフォーカスされる
<input v-focus />
```

## `Vue.directives()` - カスタムグローバルディレクティブ

カスタムディレクティブをVueインスタンス全体でグローバルに使用できるようにするには、次のように定義する。

```javascript

Vue.directive('focus', {
  inserted: function (el) {
    el.focus()
  }
})
```    

## `filters` - フィルター

フィルターは、単に値を変更してそれを返すために使用される。
それらは、ムスタッシュ構文と`v-bind`ディレクティブの両方で使うことができる。
  
コンポーネントでフィルターを定義するには、次のように定義する。

```vue
<script>
export default {
    filters: {
        capitalize: function(value) {
            if (!value) return ''
            value = value.toString()
            return value.charAt(0).toUpperCase() + value.slice(1)
        }
    }
}
</script>
```

定義したcapitalizeフィルターは次のように使うことができる。

```vue
<span>{{ msg | capitalize }}</span>
```

または、以下のように`v-bind`でも使うことができる。

```vue
<a v-bind:href="url | capitalize">My capitalized link!</a>    
```

### `Vue.filter()` - グローバルフィルター

グローバルフィルターは通常のフィルターと同じだが、一度定義すると、すべてのVueインスタンスまたはコンポーネントで使用可能。

```javascript
import Vue from 'vue'

Vue.filter('focus', {
    capitalize: function(value) {
        if (!value) return ''
        value = value.toString()
        return value.charAt(0).toUpperCase() + value.slice(1)
    }
})
```

## Vue Router

Vue Routerは、Vueを使用してクライアント側でルーティングシステムを設計するために使われる。

### Vue Routerを使い始める

ルーターの使用を開始するには、ルーターをインストールする必要がある。
手順を紹介する。

#### Vue Routerのインストール
  
npmを使用してインストールする（推奨）。

```bash
npm i vue-router --save
``` 
 
次のファイルを含めることでもインストールできる。

```vue
<script src="/path/to/vue.js"></script>
<script src="/path/to/vue-router.js"></script>
```

インストール後、VueにVueRouterを使用するよう指示する。
次の通り。

```javascript

import Vue from 'vue'
import VueRouter from 'vue-router'

Vue.use(VueRouter)
```    

ルートにバインドされているコンポーネントは、ページのどこかにレンダリングする必要があります。これは次のように`router-view`タグを使って宣言される。

```vue
<div id="app">
    <div>
        Hello World!
    </div>
    <router-view></router-view>
</div>
```

#### ルートの定義

各ルートには、独自の固有のコンポーネントがバインドされる。以下のようにルートを定義できる。

```javascript
const routes = [
  { path: '/foo', component: require('./path/to/foo/component') },
  { path: '/bar', component: require('./path/to/bar/component') }
]

const router = new VueRouter({
  routes  // `routes: routes`の省略記法
})
```

ユーザーのブラウザの履歴へルートを残したい場合は、以下のように履歴モードをアクティブにする必要がある。

```javascript
const router = new VueRouter({
  mode: 'history',
  routes  // `routes: routes`の省略記法
})
```

次に、ルートをVueインスタンスにアタッチする。

```javascript
const app = new Vue({
  router
}).$mount('#app')
```

履歴モードを使用している場合、すべてのリクエストを`index.html`ファイルにリダイレクトしてVueが残りの処理を行えるようにするには、Webサーバーの設定をする必要がある。そうしないと、ページ上でブラウザを更新することにより、そのページが実際にはサーバー上に存在しないため、**404が返されてしまう**ことに注意。

### `<router-link></router-link>` - ルーターリンク

ルーターリンクは、ページを更新せず、必要なコンポーネントのみを取得するため（そして履歴モードで履歴にURLをプッシュするため）特別なもので、新しいページに切り替わったように見える。

ハイパーリンク（`a`タグ）の代わりに、`router-link`を次のように使用する必要がある。

```vue
<router-link to="/foo">Go to foo</router-link>
```

### 高度なルーティング

Vue Routerはには単純なルーティング機能以外に、ルーティングを処理する優れた方法を他にも用意している。

#### 動的ルーティング

動的ルートは、取得するいくつかのパラメータを持つ一連のルートを照合するために使用される。

動的ルートは、通常のルートと同様に定義されるが、動的セグメントの先頭にコロンが付いている。

```javascript
const routes = [
  { path: '/user/:username', component: require('./path/to/user/component') },
]
```

これで、`/user/adnanbabakan`、`/user/dev/`または`/user/vue`などのルートは全て有効になる。

以下のようにルート内の`username`対応するコンポーネントには次のようにしてアクセスすることができる。

```javascript
<div>This is {{ $route.params.username }}'s profile!</a>
```

##### 動的ルートのパラメーター変更への対応

上記の例を考えてみよう。ユーザが`/user/adnanbabakan`から`/user/dev`に移動する場合、同じコンポーネントをレンダリングしようとするので、Vueは以前のインスタンスを破棄しない。`$route`オブジェクトで見ることのできるどんなparamsの変化にも対応するためにライフサイクルフックが呼び出されることはない。

```vue

<script>
  export default {
    watch: {
      $route(to, from) {

      }
    }
  }
</script>
```    

#### 404ルーティング

すべてのWebサイトには、優れた404ルートが必要だ。Vue Routerでは、最後にアスタリスクルート`*`を定義して、定義されていないすべてのものをキャッチすることができる。

アスタリスクルートは、他のルートの最後とその後に定義する必要がある。そうしないと、**このアスタリスクルートは他のすべてと一致し、ルーティングシステムを破壊してしまう**ことに注意だ。
  
そのためには、以下のコードをご覧ください。

```javascript
const routes = [
     // 他のルートを書いた後に404となるルートを書く
     {
       path: '*',
       component: require('./path/to/404/component'
     }
]
```
    

#### アスタリスクルート

アスタリスクを使用すると、別の種類の動的ルートを照合可能だ。動的ルートは2つのスラッシュ間の動的セグメントだけを照合可能だが、アスタリスクはそれとは別のことができる。

次のルートを見てみよう。

```javascript
const routes = [
    {
      path: '/user-*',
      component: require('./path/to/user/component')
    }
]
```

このように書くことで、`/user-adnan`、および`/user-dev`のようなルートでページはレンダリング可能だ。

`$route.params`を使うことによってと呼ばれるプロパティが`pathMatch`と呼ばれるプロパティをもつことができる。

このプロパティはアスタリスクと一致した部分が含んでいる。

たとえば`/user-adnan`ページの`$route.params.pathMatch`ははが返され`adnan`を返す。

### 名前付きルート

名前付きルートは、短い名前で長いルートパターンにアクセスするために使用される。
 
次のようなパターンがあるとする。

```javascript

const routes = [
  {
    path: '/user/profile/setting/',
    component: require('./path/to/user/component')
  }
]
```

次のように名前を定義できる。

```javascript
const routes = [
  {
    path: '/user/profile/setting/',
    component: require('./path/to/user/component'),
    name: 'settings'
  }
]
```

これで、リンクは次のように書ける。

```javascript

<router-link :to='{name: "settings"}'>
    Profile settings
</router-link>
```
    
代わりにこう書くこともできる。

```vue
<router-link to="/user/profile/setting/">
    Profile settings
</router-link>
```

オブジェクトを`to`属性に渡すときは、**バインドする必要がある**ことに注意だ。

#### パラメータ付きの名前付きルート

先述の例のように、一部のルートにはパラメータがある場合があるがそれらの名前も定義できる。

```javascript

const routes = [
  {
    // usernameというパラメータを持っているが名前を付けることが可能
    path: '/posts/from/:username',
    component: require('./path/to/posts/component'),
    name: 'posts'
  }
]
```
    
そして、これのリンクを作成する時は、次のように書くことができる。

```javascript

<router-link :to='{ name: "posts", params: {username: "adnanbabakan"} }'>Profile settings</router-link>
```    

### プログラムによるナビゲーション

先に書いたように、`<router-link></router-link>`を使用してルーターリンクを作成することができるが、プログラムでユーザーをリダイレクトする必要がある場合はどうだろうか。さて、このコードでそれを行うことができる

```javascript

router.push('/foo');
``` 

このコードはユーザーを`/foo`にリダイレクトする。これは特に、ログイン後のリダイレクトなどの状況で使用される。

#### プログラムによる名前付きナビゲーション

このような名前付きルートにも`router.push()`を使うことができる。

```javascript
router.push({name: 'myRoute'});
```    

パラメータのある場合のプログラムによるナビゲーション

同様に`router.push()`は次のようにparamsと一緒にリダイレクトするために使用できる。

```javascript
router.push({name: 'myRoute', params: {paramOne: 'Hello', paramTwo: 'Salam'}})
``` 

### ルートリダイレクト

ルートは、次のように相互にリダイレクトされるように定義できる。

```javascript

const routes = [
  {
    path: '/foo',
    redirect: '/bar'
  }
]
```    

#### 名前付きリダイレクトのルート


次のように、ルートを名前付きルートにリダイレクトすることもできる。

```javascript

const routes = [
  {
    path: '/foo',
    redirect: { name: 'myRoute' }
  }
]
```
    

#### 動的ルートリダイレクト

次のように、宛先を評価する関数を使用してルートをリダイレクトできます。

```javascript

const routes = [
  {
    path: '/foo',
    redirect: to => {
      // the function receives the target route as the argument
      // return redirect path/location here.
    }
  }
];
```
    
#### パラメータを使用したルートリダイレクト

ターゲットルートにパラメータがある場合は、リダイレクト先にも渡すことができる。

```javascript

const routes = [
  {
    path: '/profile/:username',
    redirect: '/user/:username'
  }
]
```    

### ルートエイリアス

ルートエイリアスとは、１つのルートがアクセスされるための複数のアドレスをもつことができるとい機能だ。

次が例。

```javascript
const routes = [
  {
    path: '/foo',
    alias: '/bar'
  }
];
```

これで`/foo`というルートは`/bar/`でもアクセスすることができる。

１つのルートは複数のエイリアスを持つこともできる。

```javascript

const routes = [
  {
    path: '/foo',
    // 配列に複数のエイリアスを指定できる
    alias: ['/bar', '/baz']
  }
];
```