#2 Rails × Vue.jsで動的なページをSPAさせる

[前回](https://qiita.com/divclass123/items/09496753be14b892e4f0)
json形式でrailsからデータを引っ張ることができたので、その引っ張ってきたデータをもとに
Vue.jsのほうにフロント部分を記述できればいいなと思っています。


https://www.techpit.jp/courses/123/curriculums/126/sections/935/parts/3581
今回もこの教材を参考にしています。
著作権に引っかからないように、このコードの部分を自分の実装したいコードに落とし込んで説明していきます。

# Vue.jsを書いていく

**app/javascript/app.vue**

```vue

<template>
  
</template>

<script>
import axios from 'axios';

export default {
  methods: {
    setDrink: function(){
      axios.get('/api/user/:id')
        .then(response => (
          this.drinks = response.data
        ))
    }
  }
}
</script>
```

 こんな感じで書いていきます。

```js
import axios from 'axios';
```

と書くことにより、axiosというモジュールをインポートしています。
axiosが非同期通信で必要と言うことでしたが、具体的にどういったときに必要なのかいまいち理解できていません。が一旦先に進みましょう。


```js
export default {
  methods: {
    setDrink: function(){
      axios.get('/api/user/:id')
        .then(response => (
          this.drinks = response.data
        ))
    }
  }
}
```

上記のコードではsetDrinkという関数を定義しています。

   axios.get('/api/user/:id')

というコードでは、APIを呼び出しています。
.getはHTTP動詞のgetです。

        .then(response => (
          this.drinks = response.data
        ))

.then()で通信が成功したときに行う処理を書きます。

通信できたら、/api/user/:idにアクセスしたときのレスポンスのデータを
this.drinksに代入します。

drinksをまだ定義してないので、それを定義しましょう

```js
  data: function (){
    return{
      drinks: "drinks"
    }
  },
  methods: { ,,,,,,
```

dataではそのファイルで保持しときたいデータを定義します。

今回は、特定のユーザーのコーヒーの投稿のデータをdrinksプロパティに格納しておきます。

これでaxiosを使って、特定のユーザーのコーヒーの投稿のデータを呼び出すメソッドを記載しましたが、
そのメソッドがどういったときに呼ばれるのかを書く必要があります。

```js
export default {
  data: function (){
    return{
      drinks: "drinks"
    }
  },
  mounted () {
    this.setDrink();
  },
  methods: {
    setDrink: function(){
      axios.get('/api/user/:id')
        .then(response => (
          this.drinks = response.data
        ))
    }
  }
}
```

  mounted () {
    this.setDrink();
  },

と書くことにより、app.vueファイルが読み込まれた時点でsetDrink関数が呼び込まれます。


# 取得したデータをビューに表示


```vue
<template>
<ul>
  <li v-for="drink in Drinks" :key="drink.id">
    {{drink.name}}
    {{drink.price}}
  </li>
</ul>
</template>
```

一旦drinkのnameとpriceだけを表示させることにします。


v-forとは、each文みたいな感じで、drinksという配列を一つ一つ取り出して、ローカル変数drinkが配列の
要素一つ一つなのです。

**users/show.html.erb**

に

```erb
<%= javascript_pack_tag 'hello_vue' %>
```

と記述して、うまいこと呼び出してるつもりだけど、、、。

http://localhost:3000/users/7
にアクセスしたときに、

xhr.js:175 GET http://localhost:3000/api/users/:id 404 (Not Found)

Property or method "Drinks" is not defined on the instance but referenced during render.

とかなっていて、うまくいっていない

  <li v-for="drink in Drinks" :key="drink.id">

ではなく


  <li v-for="drink in drinks" :key="drink.id">

だった。。

あとは、      axios.get('/api/users/7')
に書き換えたらうまくいくが

      axios.get('/api/users/:id')
だと上手くいかない。。。

んーー、やっかいなことになった。。。
これは長丁場になるぞ。。。。
あまりにも無理だったらパラメーターを指定しなくていいページのSPAも考えていく。

idパラメーターの扱いがやっかい。。。

まず、整理すると、

localhost:3000/users/7にリクエストが来る
↓
users#showの処理が動く
↓
処理の結果生成されたビューが表示
↓
そのビューの中に、
<%= javascript_pack_tag 'hello_vue' %>
がある
↓
hello_vueが表示
↓
hello_vue.js ファイルを介してjavascript/packs/app.vueファイルを読み込みます。

↓
app.vueが読み込まれる
↓
よみこまれた瞬間setDrinks()が呼び出されて、
      axios.get('/api/users/:id')
とサーバーにgetリクエストを送る。

まず、さーてどうしようかなー。


現在のURLを取得できればなんとか行けそう？

this.$route.path
で現在のurlが取得できるらしい。
なんか無理だった。

document.URLはjsのメソッドなので、いけるかなーーーー

console.log(document.URL);
vueファイルのscript部分に書いたらいけた。

http://localhost:3000/users/7

しっかりと現在のパスが取得できた。
ただ、やりたいことは
      axios.get('/api/users/:id')
これなので、どうしたものか。



console.log(location.pathname);

で、users/7が取得できた！
これでどんなユーザーでもそのユーザーの投稿が見れるはず！

      axios.get('/api' + location.pathname)
 と書いた！！

したら、

![スクリーンショット 2021-08-07 15.44.29.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/653881/877492aa-b340-a909-18cf-6aefdc55ca75.png)


キターーーーーー！！！！！

めっちゃ部屋で叫んだｗｗｗｗｗｗｗｗｗｗｗｗｗ
これは嬉しすぎるｗｗｗｗｗｗｗ


わかりずらいですが
aaaa 3000
dddd 3000
とかが、コーヒーの名前と値段です
それらが取得できてるので、他にもコーヒーのexplainとかも取得できるでしょう！
よしやっとここからrailsからjson形式で取得したデータをもとにvueを書けるぞ！


だがしかし、画像はしっかりrailsから拾えるのか、、、
{{drink.image}}とやれば画像が表示されると思った自分が甘かった。。。。


https://qiita.com/youichiro/items/2987cd9b4ab29691eb77

この記事を参考に色々やっていこう。

いいね！！明日やっていく！