2019年11月28日 14:00
前回ページごとに動的にタイトルをつけるため、Vue Router のナビゲーションガードを使って画面遷移前にデータの取得するようにしましたが、肝心のタイトル変更がうまくいきませんでした。
しかし、vue-meta
を使ったところあっさりと解決しました。
Vue MetaはNuxt.jsでも使われている、meta タグの値を変更するライブラリです。
Nuxt.js でなくても Vue を使っていれば使うことができます。
多くのサイトではトップページ以外のページで、[トピック名 - サイトタイトル]や[トピック名 | サイトタイトル]のように、サイトタイトルが必ず末尾または先頭に来るようにしていますが、vue-meta でも同じことが簡単にできます。
yarn(npm)で追加し、Vue.use()
で登録します。
yarn add vue-meta
import Vue from "vue";
import VueMeta from "vue-meta";
Vue.use(VueMeta);
Vue
の起点となるApp.vue
コンポーネントと、投稿を表示するページ/posts
コンポーネントと、投稿の詳細ページ/posts/:id
コンポーネントがある場合で考えます。
App.vue
コンポーネントでは以下のように書きます。
export default {
metaInfo() {
return {
titleTemplate: titleChunk =>
titleChunk ? `${titleChunk} - サイトタイトル` : "サイトタイトル"
};
},
data() {
return {
//
};
}
/** 省略 */
};
titleChunk に値があった場合は末尾にサイトタイトルを付与し、なければサイトタイトルだけを表示します。
こうすることで以降のコンポーネント内で、title が設定されていない場合はサイトタイトルだけが表示されるようになります。
/posts
の場合は次のように書きます。
export default {
metaInfo: {
title: "投稿一覧"
}
}
/** 省略 */
};
/posts/:id
の場合は次のように書きます。
export default {
metaInfo() {
return {
title: this.post.title
};
},
data() {
return {
post: {}
};
},
async beforeRouterEnter(to, from, next) {
const id = to.params.id;
const res = await axios.get(`/api/posts/${id}`);
next(vm => (vm.post = res.data));
}
/** 省略 */
};
/posts/:id
のように動的にデータが変わる場合は、metaInfo
を関数として定義します。
metaInfo()
はデータが変更されれば反映されるのですが、反映されるまでのラグが気になったので、Vue
Router の beforeRouteEnter
と組み合わせることで、遷移する頃にはデータが揃っている状態にできます。