Vue.jsで連想配列を使おう！

# 🍪Vue.jsで連想配列を使おう！

はじめまして、[s4na🐧](https://twitter.com/s4na_penguin)と申します。
今回はじめてQiitaの記事を書きます。

今回書く内容は、少し前にVue.jsで実装していたら躓いた連想配列の利用方法です。
一時期は「計算量が増えるけど、連想配列を使わないで実装してしまおうかな・・・😢」と思ったこともあるくらい大きく躓きました。

少しでも私と同じところで躓く人の力になればと思い、今回筆をとりました。🖋

## RailsのViewからVue.jsに連想配列を渡す方法

まずはRailsのViewからVue.jsに連想配列を渡す方法について書いていきます。

この方法は、Rails側からVue.jsに初期値を渡す際に使います。
もちろん、APIを作ってそちらで渡してもいいのですが、それだとAPI分の通信量が増えてしまうので、私はViewから渡しています。

- 補足：RailsのView = [MVC](https://ja.wikipedia.org/wiki/Model_View_Controller)のView

### ControllerでJSON化しておく

- 補足：Hashのまま渡すと、Vue.jsがParseできないです。フロントで無理にパースしてもいいのかもしれませんが、サーバーサイドでできることはサーバーサイドでしたほうが良さそうです

```ruby
@foo = JSON(foo)
```

### View

- 補足：
  - RailsのTemplate Engineは[slim](https://github.com/slim-template/slim)で書いています
  - `@foo`, `@baa`みたいに値を複数渡す場合もあるので、`#js-el-data-foo`のように名前を区切ると便利です。

```slim
#js-el # 👈Vue.jsがマウントするDOM
  #js-el-data-foo
    = @foo # 👈渡したい値 その１
  #js-el-data-baa
    = @baa # 👈渡したい値 その２
```

### Vueインスタンス

Vue.js側では、ViewのDOMの`innerText`を取得し、JSON化して`data`に入れ込みます。

```javascript
<script>
export default {
  data: () => {
    return {
      reservations: {}
    }
  },
  created: function() {
    //                 👇JSONが連想配列になる                            👇JSONで受け取る
    this.memos = JSON.parse(document.querySelector('#js-el-data-foo').innerText);
  }
}
</script>
```

## Vueインスタンスで連想配列をループ表示する方法

連想配列の表示は`連想配列[key]`とする必要があり、そのためには`key`の集合である`keys`が必要になります。

- 補足：テンプレートエンジンには`Pug`を使用しています

```javascript
<template lang="pug">
  .foo(v-for="key in keys")
    | {{ foo[key] }}
</template>
<script>

export default {
  data: () => {
    return {
      reservations: {},
      keys: []
    }
  }
}
</script>

```


## Vueインスタンス内で連想配列に情報を追加する方法

追加する際は[`$set`](https://jp.vuejs.org/v2/api/#vm-set)メソッドを使いましょう。

これは書こうとした時、めっちゃハマりました。😭
この記事を書こうと思った原点でもあります。

他の言語やフレームワークを利用していたりすると、「`val['key']`で値を代入できるのでは？」と考えてしまうこともあるかと思います。（私はそうでした。）

Vue.jsでは、JavaScriptの仕様で、連想配列に要素を追加した時に検知できません。
なので、変更検出が可能なメソッドを利用する必要があります。（公式ドキュメントを読めば気づけるけど、読んでなかった😈）

[Vue.js#オブジェクトの変更検出の注意](https://jp.vuejs.org/v2/guide/list.html#%E3%82%AA%E3%83%96%E3%82%B8%E3%82%A7%E3%82%AF%E3%83%88%E3%81%AE%E5%A4%89%E6%9B%B4%E6%A4%9C%E5%87%BA%E3%81%AE%E6%B3%A8%E6%84%8F)

```javascript
export default {
  data: () => {
    return {
      foo: {}
    }
  },
  methods: {
    addFoo: function(key, hoge) {
      this.$set(this.foo, `key`, hoge);
    }
  }
```

## 連想配列から要素を削除する方法

削除する際は[`$delete`](https://jp.vuejs.org/v2/api/#vm-delete)メソッドを使いましょう。
JavaScriptを書いていると、`delete`メソッドで削除してしまったりすることがあると思います。（私はそうでした）
それだと`$set`と同様に、Vue.jsが要素数の変化を検知できないので、`$delete`を使う必要があります。

```javascript
  methods: {
    deleteFoo: function(key) {
      this.$delete(this.foo, key);
    }
  }
```

## Vueインスタンスで連想配列をAPIで取得する方法

```javascript
  methods: {
    token () {
      const meta = document.querySelector('meta[name="csrf-token"]')
      return meta ? meta.getAttribute('content') : ''
    },
    getFoo: function() {
      fetch(`/api/hogehoge`, {
        method: 'POST',
        headers: {
          'Content-Type': 'application/json; charset=utf-8',
          'X-Requested-With': 'XMLHttpRequest',
          'X-CSRF-Token': this.token()
        },
        credentials: 'same-origin',
        redirect: 'manual',
      })
        .then(response => {
          return response.json();
        })
        .then(json => {
          this.$set(this.foo, `key`, json); // 👈受け取った値を連想配列`foo`に入れる
        })
        .catch(error => {
          console.warn('Failed to parsing', error);
        })
    },
```

## まとめ

- Vue.jsで連想配列を扱うのは、癖がわかれば結構簡単！
- 時間がなくて厳しくても、触ったことのない技術を触るのであれば、何よりもまずは公式ドキュメントを全部読もう！！！
- Vue.jsならこちらの[ガイド](https://jp.vuejs.org/v2/guide/installation.html)を読もう！！！