はじめに
Nuxtを使った開発が続いたので、その知見(のようなもの)を共有したいと思います。
わざわざ単ページにするほど長くもないトピックばかりです。
aタグではなくnuxt-linkを使う
nuxt-link
というカスタムタグ(コンポーネント)はnuxt特有のもので、Vue-routerのrouter-link
のラッパーです。画面遷移に先んじて遷移先のページを読み込んでいるので、特別な事情がない限り基本はnuxt-linkを使いましょう。
気をつけてほしいのは、どこからかコピペしてきたhtmlタグにうっかりaタグが混じっているパターンです。たいていの場合はaタグでも問題にならずに動きます。一応普通に画面遷移自体はできるのですが、明らかにその画面遷移が遅いのと、Vuexの状態管理情報が消えるので、認証状態でaを使うと認証されず気づかずにエラーがでるということもあります。
aタグによる画面遷移は遅いので慣れてくるとaタグが混じってることに感覚的に気づくと思います。
window.locationの代わりに$router.pushを使う
※以下の内容はNuxtのバージョン、APIによってrouter.push()の使い方が代わるかもしれません
少なくともNuxt v2.14.0+Composition APIの場合ではですが、$router.pushは以下のようにして使います。
setup(_props: {}, { root }: SetupContext) {
root.$router.push('/test') // 飛ぶ先
return {}
},
$router.pushを使うとstoreされた情報が維持されます。逆にwindow.locationの別のページに飛ぶとstoreの情報が消えるかもしれないのでご注意を。
ページ内リンクのジャンプ
ハッシュ記号によるページ内リンク指定ですが、普通のaタグのやり方とは少し違います。
例えば、index.vueからabout.vue内にある#titleというアンカーに飛ぶというときは以下のようにnuxt-linkを貼ります。
<nuxt-link :to="{ path: 'about', hash: '#title' }">link</nuxt-link>
about.vue内では以下のようにします。
<div id="title">
とべた!
</div>
※自分の場合<a name="title"></a>
は使えませんでした。
あくまでidを指定していることに注意。
なお、この方法は同じページ内だと最初の一回しかジャンプできません。
一度リンク先に飛んでから、もう一度リンクボタンをクリックしても何も反応しません。何度でもジャンプしたいときは、Vue-scrolltoを使用してください。
また、hashを使って飛ぶ方法は$router.pushでも可能なので、何らかの処理を実行したあとにページ内リンクで飛ばしたいというときは以下のような記述で飛べます。
root.$router.push({ path: '/about', hash: 'title' })
スムーズスクロールで何度でもページ内ジャンプをしたい
モジュールとしてvue-scrolltoを使用しましょう。
yarn add vue-scrollto
nuxt.config.jsには以下のように
{
modules: [
'vue-scrollto/nuxt',
// もしもカスタムオプションをつけたいときは以下のようにする
['vue-scrollto/nuxt', { duration: 300 }],
]
}
リンクは以下のように貼ります
<nuxt-link v-scroll-to="'#here'" to>link</nuxt-link>
飛ぶ先にもid指定でhereを用意しておきます。
<div id="here">
とべた!
</div>
watchで指定した複数の要素をwatchする
これはNuxtとかCompositionAPIとか関係なしに昔から使えましたが、備忘録に。
全部の要素ではなくいくつかの複数の要素をwatchしたいというときは以下のように配列で渡します。
value1かvalue2のどちらかが変化したとき、changeと表示されます。
const value1 = ref(1)
const value2 = ref(1)
watch(
() => [value1.value, value2.value],
() => {
alert('change!')
}
)
ルート情報を取得する
ルート情報はroot.$route.path
で取得できます。
例えばメインメニューのようなものがペッジーヘッダーにあり、現在表示されているページにはアンダーバーを表示するクラスを追加したい、という要望があるかもしれません。仮に追加したいクラス名をcurrent-menu-item
としたときは、以下のようにします。
// メニュー
const menuList = [
{ name: 'index', path: '/' },
{ name: 'about', path: '/about' },
{ name: 'contact', path: '/contact' },
]
const menuClass = (path: string) => {
return root.$route.path === path ? 'current-menu-item' : ''
}
テンプレート
<ul>
<li
v-for="menu in menuList"
:key="menu.name"
:class="menuClass(menu.path)"
>
<nuxt-link :to="menu.path">{{ menu.name }}</nuxt-link>
</li>
</ul>
上記は文字列として一つのクラスを渡していますが、配列で複数のクラスを渡せるようにしたほうが応用が効きます。
タイトルを動的に変更する
Nuxtでは内部的に vue-metaを使用しています。
nuxt.config.jsを開き、head
プロパティのtitleを消し、代わりにtitleTemplateを使います。プレースホルダーとして%sを書きます。
head: {
// title: 'サイト名',
titleTemplate: 'サイト名 | %s',
}
あとは各ページコンポーネント上で、titleプロパティをいじればOK。
export default {
name: '',
head: {
title: 'ここに追加タイトル',
},
setup(){}
}
titleタグにサイト名 | ここに追加タイトル
と入っていれば成功です。
参考: Nuxt.js titleタグを各ページごとに「サイト名 + 任意の文字列」に設定
ビルド時にファイルを生成したいとき
ビルド時に特定のファイルを仕込むときに使えます。
参考 : Nuxt.jsのhooksを利用してビルド時にファイルを生成する
ページのトップに飛ぶリンクを作る
yarn add vue-backtotop
インポートについてVueは公式サイトから。以下はNuxtの場合のやり方です。
plugins/vue-go-top.jsを作ります。
import Vue from 'vue';
import GoTop from 'vue-backtotop';
Vue.use(BackToTop)
// もし`go-top`というカスタムタグを使いたいときは以下のようにする
// Vue.component('go-top', GoTop)
nuxt.config.jsのpluginsプロパティ配列に以下を追記
plugins: [
{
src: '@/plugins/vue-go-top',
mode: 'client'
}
],
テンプレート部
<BackToTop text="Topへ" />
<!-- 縦に長いページを作ると右下に自動的に表示されます -->
ただしデフォルトのデザインはそんなに格好良くないので、自分で書き換えたほうがいいです。
書き換える場合は以下のようにします。自分のデザインに書き換えたいときは適当にbuttonタグ部分を変更してください。
<BackToTop>
<button>トップへ</button>
</BackToTop>
参考 : Nuxt.js vue-go-topを使用して画像にエフェクトかける
コンポーネントを使うときはcomponentsモジュールを使う
Nuxtでコンポーネントを扱うときは、components
モジュールを使うことを強くお勧めします。
これは比較的最近のバージョンで標準化されたモジュールなので、最新版ではインストールした段階で使用できます。
古いバージョンだとモジュールをインストールすれば使用できるので、こちらを御覧ください。
今までのNuxtだと、コンポーネントを使用する際、まず使用したいコンポーネントをimportしてcomponentプロパティに使用するコンポーネントを指定してからテンプレート上で使えるようにしていました。
しかしcomponentsモジュールがあると、ただ<HelloWorld />
とテンプレート上で書くだけで同名のvueファイルが読み込まれます。NuxtのComponentモジュールがあれば、自動的にそのモジュールが呼ばれるので、モジュールだけ適当に切り分けて、後でディレクトリごとにまとめるという開発のススメ方ができますので、これが割と便利です。
なお同名のコンポーネントが存在するとエラーが出るので、こっそり違うコンポーネントが表示されることはありません。
もしかしたら古くからNuxtを使っている方も知らないかもしれないので、これはオススメです。