ヘッダのタイトルが表示されないのと、エラーページがデフォルトのままになってしまったので、そちらの修正を行います。
前回:Nuxt BridgeをNuxt3に移行。ESlintを導入
- ヘッダのタイトルが表示されない
- エラーページをカスタマイズする
- TypeError: this.$nuxt.error is not a function
- 【次回】Vuetify3のテーマと色を設定+確認ページ作成
- 今回のコミット内容
ヘッダのタイトルが表示されない
Options APIの記法
defineNuxtComponentが必要
// if using options API `head` method you must use `defineNuxtComponent`
そもそもdefineNuxtComponentで囲ってあげないと、headが認識しない。
layouts, pages, components, Mixinで使っているutils等、序でに全部変更しておきます。
<script>
- export default {
+ export default defineNuxtComponent({
- }
+ })
</script>
コンポーネントインスタンスにアクセスできない
// `head` receives the nuxt app but cannot access the component instance
localやconfigを使っている場合は自分で対応する必要があります。
Uncaught (in promise) TypeError: this.$t is not a function Uncaught (in promise) TypeError: Cannot read properties of undefined (reading 'public')
例: layouts/default.vue
head () {
+ const { t: $t } = useI18n()
+ const $config = useRuntimeConfig()
return {
- titleTemplate: `%s - ${this.$t('app_name')}${this.$config.public.envName}`
+ titleTemplate: `%s - ${$t('app_name')}${$config.public.envName}`
}
},
titleも同様ですが、次のBuilt-in Meta-componentsを使うのも良さそう。
Built-in Meta-components
Composition API書き換え前ですが、<template>内に定義できるので、先頭にあると解りやすい。
但し、TitleTemplateは対応していないのが残念だけど、TitleやMetaは入れやすい。
[Vue warn]: Failed to resolve component: TitleTemplate
例: pages/infomations/index.vue
<template>
+ <Head>
+ <Title>お知らせ</Title>
+ </Head>
export default defineNuxtComponent({
- head () {
- return {
- title: 'お知らせ'
- }
- },
Built-in Meta-componentsで動的な値
computed等で値を渡してあげれば、普通に使えます。
例: pages/infomations/[id].vue
<template>
+ <Head>
+ <Title>{{ title }}</Title>
+ </Head>
export default defineNuxtComponent({
- head () {
- return {
- title: this.title
- }
- },
-
computed: {
title () {
let label = ''
if (this.infomation?.label_i18n != null && this.infomation?.label_i18n !== '') {
label = `[${this.infomation.label_i18n}]`
}
return label + (this.infomation?.title || '')
}
},
漏れがないか確認
before(nuxt2): nuxt.config.js
// Global page headers: https://go.nuxtjs.dev/config-head
head: {
meta: [
{ charset: 'utf-8' },
{ name: 'viewport', content: 'width=device-width, initial-scale=1' }
],
link: [
{ rel: 'icon', type: 'image/x-icon', href: '/favicon.ico' }
]
},
何も設定しなくても、charsetとviewportは入っていました。
SEO and Meta · Get Started with Nuxt
faviconはデフォルトのなので、なくても問題ない。
<meta charset="utf-8"> <meta name="viewport" content="width=device-width, initial-scale=1">
エラーページをカスタマイズする
Error handling · Get Started with Nuxt
error.vue
layouts/error.vueは不要になったので削除します。
せっかくなので、Composition API+TypeScriptで書き直します。
<template>
<NuxtLayout>
<Head>
<Title>{{ title }}</Title>
<Meta name="robots" content="noindex" />
</Head>
<v-card>
<v-card-title>{{ alertMessage }}</v-card-title>
<v-card-text v-if="noticeMessage != null">{{ noticeMessage }}</v-card-text>
<v-card-actions>
<NuxtLink to="/">トップページ</NuxtLink>
</v-card-actions>
</v-card>
</NuxtLayout>
</template>
<script setup lang="ts">
const { t: $t } = useI18n()
const props = defineProps({
// eslint-disable-next-line vue/require-default-prop
error: Object
})
const title = computed(() => (props.error?.statusCode === 404) ? 'Not Found' : 'エラー')
const alertMessage = computed(() => {
if (props.error?.data?.alert != null) { return props.error.data.alert }
return $t((props.error?.statusCode === 404) ? 'system.notfound' : 'system.default')
})
const noticeMessage = computed(() => props.error?.data?.notice)
</script>
(削除前の)layouts/error.vue
参考までに、Nuxt2の時のOptions APIで書いたコードです。
Composition API(上のコード)の方がスッキリしていますね。
<template>
<div>
<v-card>
<v-card-title>{{ alertMessage }}</v-card-title>
<v-card-text v-if="error.notice != null">{{ error.notice }}</v-card-text>
<v-card-actions>
<NuxtLink to="/">トップページ</NuxtLink>
</v-card-actions>
</v-card>
</div>
</template>
<script>
export default {
props: {
error: {
type: Object,
default: null
}
},
head () {
return {
title: (this.error.statusCode === 404) ? 'Not Found' : 'エラー'
}
},
computed: {
alertMessage () {
if (this.error.alert == null) {
return this.$t((this.error.statusCode === 404) ? 'system.notfound' : 'system.default')
}
return this.error.alert
}
},
created () {
// eslint-disable-next-line no-console
if (this.$config.public.debug) { console.dir(this.error) }
}
}
</script>
動作確認
404の場合
404以外で、APIからのメッセージがない場合
存在しないメソッドを入れてみる
created () {
+ xxx
画面は真っ白
Uncaught (in promise) ReferenceError: xxx is not defined
Nuxt3入門(第6回) – アプリケーションで発生するエラーに対応する | 豆蔵デベロッパーサイト
クライアントサイドで例外をスローするとデフォルトは非クリティカルなエラーになり、 エラーページは表示されません。 明示的にエラーページを表示する場合は、showErrorまたは、createErrorの引数でfatalをtrue
つまりブラウザ上でエラーになった場合、画面表示は変わらない。
なので、これでも結果は同じです。
+ throw 'エラー'
+ throw createError('エラー')
showErrorを呼び出してみる
created () {
+ throw showError({ statusCode: 500, message: 'サーバーエラー' })
Uncaught (in promise) Error: サーバーエラー
APIからのメッセージがある場合
created () {
+ throw showError({ statusCode: 500, message: 'サーバーエラー', data: { alert: 'エラーメッセージ', notice: '追加情報' } })
Uncaught (in promise) Error: サーバーエラー
TypeError: this.$nuxt.error is not a function
$nuxt.errorがなくなっているので、throw showErrorに変更します。
例: utils/application.js
- this.$nuxt.error({ statusCode, alert: data.alert, notice: data.notice })
+ throw showError({ statusCode, data: { alert: data.alert, notice: data.notice } })
【次回】Vuetify3のテーマと色を設定+確認ページ作成
package.jsonとnuxt.config.ts(.js)の新旧を比較して、漏れがない事を確認。
PWAは使ってなかったので導入しない。Vuetifyの移行していない設定が残っている。
残りはデザイン崩れ(Vuetify)と、テスト(Vitest)の導入と既存テスト(Jest)の移行です。
いよいよ終わりが見えてきましたが、それぞれ修正量が多そうな予感がします。
→ Nuxt BridgeをNuxt3に移行。Vuetify3のテーマと色を設定+確認ページ作成
“Nuxt BridgeをNuxt3に移行。ヘッダタイトルとエラーページを修正” に対して1件のコメントがあります。