トップ/記事一覧

Nuxt.js の nuxt-child を使って、Asana のような2カラムレイアウトUIを構築する

📆August 20, 2020🔖 NuxtJS

SPA(Single Page Application)でよく見る2カラム構造を nuxt-child という機能を使って作ってみたブログです。

この UI は SPA プロダクトによくある作りで、一覧画面と詳細画面を同じ画面上で描画することができて、一覧性を保ちつつ、詳細を閲覧・入力したい要件のプロダクト等でよく見かける UI です。

以下 Asana のスクリーンショット(gif)です。こんなイメージのものを作りたいと思います。

Asana の 2カラム構造
Asana の 2カラム構造

タスクを選択すると、同時に URL も切り替わります。なので URL を直接入力してページにアクセスした場合でも、詳細画面が開かれた状態になります。

以下のように要件をまとめ、サンプルコードを書いてみました。

要件

  • 左カラムにはタスクの一覧が表示される
  • タスクをクリックすると、ページ遷移し URL が変更される(ページ全体の再読み込みは走らない)
  • タスクをクリックすると、右カラムでタスク詳細が開かれる
  • nuxt-child を使って要件を実現する

    nuxt-child の細かい説明は、公式ドキュメントに譲りますが、ざっくりと要点だけ書くと

  • <nuxt-child> と書くと、その部分に子ページの要素が流し込まれる
  • 親ページのファイル名と、子ページが格納されるディレクトリ名を一致させる
  • の2点を満たせば、同一画面上に別のページを表示させることができます。

    以下は例ですが、以下のようなディレクトリ構造になっていれば nuxt-child が機能します。

    nuxt-child のディレクトリ構造の例(公式 Docs より)
    nuxt-child のディレクトリ構造の例(公式 Docs より)

    サンプルコードを書いた

    コードは以下のような感じになりました。(サンプルコードの全ては GitHub で公開しています。また、サンプルプロジェクトは Netlify 上にデプロイされています。記事の最後にそれぞれリンクを張っておきます。)

    親(index.vue)の template

    JavaScript

    <template> <div class="container"> <div class="l-list-area"> <ul class="list"> <li class="list__item" @click="_onClickAdd"> 追加 </li> <li v-for="(_, index) in tasks" class="list__item" :key="_" @click=" () => { $router.push(`/tasks/${index}`) } " > {{ _ }} </li> </ul> </div> <div class="l-detail-area"> <nuxt-child /> </div> </div> </template>

    <nuxt-child> を描画するエリアと、一覧を表示するエリアを分けています。タスクをクリックすると push 遷移し、 <nuxt-child> の部分に子ページが流し込まれます。追加ボタンを押したときはタスクが追加されます(タスクの追加部分のロジックについては割愛します。)

    先述のとおり、親ページのファイル名は、index.vue なので、nuxt-child として機能させるのは、表示させたい子ページを index というディレクトリ内に作る必要があります。

    以下は小ページ(_id.vue)の template

    JavaScript

    <template> <div class="l-detail"> {{ $route.params.id }} </div> </template>

    サンプルコードでは、URL のパラメータをそのままレンダリングしているだけですが、この id をキーにして、非同期で fetch したりすることで、タスクの詳細情報をレンダリングすることができるようになったりします。

    成果物

    以下のようなタスク管理アプリが完成しました。左カラムにはタスクの一覧、右カラムにはタスクの詳細が表示されています。タスクをそれぞれクリックすると、URL が遷移し、また右側のカラムの詳細も変化していることが分かると思います。

    nuxt-child のサンプルプロジェクト
    nuxt-child のサンプルプロジェクト

    まとめ

    このように nuxt-child を使うと簡単にネストしたルーティングを UI 上で同一ページ内で表現することができます(というのを最近知ったので書いたという節があります)。

    ルールさえ覚えてしまえばルーティングの設定をすることなく、簡単にこのような UI を作ることができるのでメチャメチャオススメです。

    🐈

    サンプルコードは GitHub で公開しています。また、動くサンプルプロジェクトは Netlify で公開しています。

  • サンプルコード https://github.com/35d/nuxt-child-sample
  • サンプルプロジェクト https://priceless-hermann-5b491b.netlify.app/tasks/1