【Nuxt.jsで近くのお店を探すアプリを作成】#5 asyncData

Web

今回の目標

前回はasync/awaitを使った非同期処理について説明しました。現在位置の取得とお店一覧の取得処理がasync/awaitを使うことによって少しすっきりしたコーディングができたと思います。

【Nuxt.jsで近くのお店を探すアプリを作成】#4 async/await
非同期処理を連続して行う場合には、コーディング的に読みにくくなることがあります。今回はそれを解決する方法であるasync/awaitについて少し説明します。また非同期処理についても少し触れます。

今回は詳細ページへの遷移、お店の詳細情報の取得を実装していきます。

詳細ページへの遷移

プロジェクト作成時に、pagesディレクトリに「index.vue」に加え、「_id.vue」を作成していました。これが詳細ページになります。詳細ページはクエリパラメーターとしてお店のIDを受け取り、そのIDに該当するお店の詳細を表示します。

まずは一覧から該当のお店が選択された場合に詳細ページに遷移する処理を実装しましょう。

Nuxt.jsのページについてはこちらの記事をみていただければと思います。

簡単!Nuxt.jsにおけるページの構成方法
Nuxt.jsではpagesディレクトリにVueファイルを配備するだけで簡単にページ構成を作ることができます。この記事ではさらにNuxt.jsのページの機能について紹介をしていきます。

ページ遷移の方法は、nuxt-linkとRouterインスタンスのgo()があります。今回は後者を使用します。特に理由はありませんが、こちらのほうが扱いやすいというだけです。

<ul>  
  <li
    v-for="shop in shops" 
    :key="shop.id" 
    @click="$router.push(`/${shop.id}`)" 
    class="card">
    <!-- list contents ->
  </li>
</ul>

今回お店の一覧は「ul-li」で作成しており、v-forによって取得したお店をループして表示しています。今回遷移先は「/{id}」としたいので「$router.push(/${shop.id})」としています。

確認のために「_id.vue」を次のようにして実際に遷移してみてください。

<template>
  <p>{{$route.params.id}}</p>
</template>

コンテキストパスに設定されたクエリパラメーターと同じ値が表示されればOKです。

お店情報の取得

クエリパラメーターのIDからお店の情報を取得してみましょう。使用するAPIは変わらずグルメサーチAPIを使用します。

お店の一覧を取得した時と違うのは、送信するパラメーターです。お店の一覧を取得するときは現在位置を設定しましたが、ここではお店のIDを設定します。IDは一意なので当然該当する1件のデータが取得できます。

$axios.get("http://localhost:3000/api/gourmet/v1/",
  {
    params: {
      key: process.env.apikey,
      id: this.$route.params.id,
      format: "json"
    }
  }
)

データの取得タイミングですが、一覧取得と同様にmountedの場合に取得しても良いのですが、今回はasyncDataを使用したいと思います。

asyncDataによるデータの設定

asyncDataは、ページ専用のメソッドで、外部APIからデータを取得してそのページのdataとして設定します。

よくわからないかもしれませんが、まずはページ用のコンポーネント専用のメソッドということを覚えてください。他にもページ専用のメソッドやプロパティがありますが、ここでは取りあげません。

ではasyncDataについて少しずつ解説していきます。

asyncDataの実行タイミング

まずasyncDataが実行されるタイミングについて説明します。

通常のVue.jsコンポーネントにはライフサイクルフックと言って、createdやmountedなどコンポーネントの生成〜破棄の間にいくつか実行されるメソッドがあります。ライフサイクルフックについてはこちらの記事を参考にしてください。

【Vue.js】ライフサイクルフックの基本を利用方法と共に解説!
Vueにはライフサイクルと言って、インスタンスの生成から破棄までの間に実行される関数がいくつかあります。Vueで開発する上では必要不可欠な知識なので、具体的な利用例を基に基本を学んでいきましょう。

asyncDataはこのライフサイクルフックの前に実行されます。つまり最初に実行されるbeforeCreateよりも前に実行されます。

公式ドキュメントには、「コンポーネントがロードされる前に毎回呼び出されます。」と記述されています。とりあえず、「コンポーネントロードする前に必要なデータ先にとってきとくねー。」くらいでいいかなと思います。

asyncDataの実装

asyncDataを実装する場合、その返値はPromiseオブジェクトでなければいけません。そうなると少し複雑なようなきがしますが、前回使ったasync/awaitを使うことでスッキリ実装することができます。

まずはおまじないと思って使ってみましょう。

export default() {
  async asyncData() {
    //データの取得
    const { data } = await $axios.get("http://localhost:3000/api/gourmet/v1/",
      {
        params: {
          key: process.env.apikey,
          id: this.$route.params.id,
          format: "json"
        }
      }
    );
    //取得したデータをdataにマージ
    return {
      shop: data.results.shop[0]
    }
  }
}

asyncDataではreturnしたオブジェクトがそのままdataプロパティとして設定されます。つまり次と同義になります。

export default {
  data() {
    return {
      shop: data.results.shop[0]
    }
  }
}

しかし、これでは動作しません。先ほど説明した通り、asyncDataはコンポーネントがロードされる前に実行されます。これがどういうことかというと、axiosのパラメータとして設定している、「process.env」や「this.$route」などが参照できません

では、どうすればよいのでしょうか。

contextオブジェクト

contextオブジェクトは、asyncDataなどコンポーネントがロードされていない場合に実行される処理で使用されるオブジェクトです。contextオブジェクトには環境変数(env)やルーティングの情報が含まれています。

詳細は割愛しますが、公式ドキュメントのリンクを貼っておきます。

API: コンテキスト
`context` は、従来 Vue コンポーネントが使用できないオブジェクト/パラメータを Nuxt から追加で提供します。`context` は `asyncData`、`plugins`、`middlewares`、`modules` や `store/nuxtServerInit` といった nuxt の特別な...

contextオブジェクトは引数として参照することができ、必要なプロパティを指定します。今回の場合、最終的に次のようにします。

export default {
  scrollTop: true,
  async asyncData({ $axios, params, env, redirect }) {
    try {
      //データの取得
      const { data } = await $axios.get("http://localhost:3000/api/gourmet/v1/",
        {
          params: {
            key: env.apikey,
            id: params.id,
            format: "json"
          }
        }
      );
      //対象データがない場合は一覧ページに戻る
      if (data.results.shop.length <= 0) {
        redirect("/");
      }
      //dataにマージ
      return {
        shop: data.results.shop[0],
        error: undefined
      };
    } catch (error) {
      //エラーが発生した場合のdataへのマージ
      return {
        shop: undefined,
        error: {
          message: "データの取得に失敗しました"
        }
      };
    }
  }
}

contextオブジェクトで参照しているのは、Vueインスタンスプロパティに設定している$axios、クエリパラメーターのparams、環境変数のenv、ページを遷移する際に使用するredirectです。

これでdataプロパティにshopプロパティが設定されるのでそれを使用して画面に表示しましょう。

あとがき

これでアプリケーションの基本的な部分の説明は終わりです。あとはデザインを組み上げれば完成です。

ホットペッパーAPIを使えばここからいろいろ機能を追加して、さらに良いアプリケーションを作ることができると思います。

興味のある方は是非挑戦してみてください。

 

- Nuxt.jsのおすすめ書籍はコチラ -

 

 

コメント

タイトルとURLをコピーしました