トップ/記事一覧
Nuxt.js の nuxt-child を使って、Asana のような2カラムレイアウトUIを構築する
📆2020/08/20🔖 NuxtJS
⚠ この記事は最終更新日から1年以上が経過しています。内容が古い箇所がある可能性があるためご注意ください。
SPA(Single Page Application)でよく見る2カラム構造を nuxt-child という機能を使って作ってみたブログです。
この UI は SPA プロダクトによくある作りで、一覧画面と詳細画面を同じ画面上で描画することができて、一覧性を保ちつつ、詳細を閲覧・入力したい要件のプロダクト等でよく見かける UI です。
以下 Asana のスクリーンショット(gif)です。こんなイメージのものを作りたいと思います。
タスクを選択すると、同時に URL も切り替わります。なので URL を直接入力してページにアクセスした場合でも、詳細画面が開かれた状態になります。
以下のように要件をまとめ、サンプルコードを書いてみました。
要件
nuxt-child を使って要件を実現する
nuxt-child の細かい説明は、公式ドキュメントに譲りますが、ざっくりと要点だけ書くと
の2点を満たせば、同一画面上に別のページを表示させることができます。
以下は例ですが、以下のようなディレクトリ構造になっていれば nuxt-child が機能します。
サンプルコードを書いた
コードは以下のような感じになりました。(サンプルコードの全ては 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 を使うと簡単にネストしたルーティングを UI 上で同一ページ内で表現することができます(というのを最近知ったので書いたという節があります)。
ルールさえ覚えてしまえばルーティングの設定をすることなく、簡単にこのような UI を作ることができるのでメチャメチャオススメです。
🐈
サンプルコードは GitHub で公開しています。また、動くサンプルプロジェクトは Netlify で公開しています。