前言
有時候我們在開發系統時,也會希望網頁的 title 隨著頁面變化,例如首頁、關於我們等,那在 SPA 的 Vue 該怎麼做呢?
從 router 設置
第一種方式相對比較簡單一點,以往我們在設置 router 的導航守衛都會在這邊這樣寫
1 2 3
| { meta: { requiresAuth: true }, },
|
並搭配導航守衛 (該範例取至 RagnarokShopV3)
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20
| router.beforeEach((to, from, next) => { if (to.meta.requiresAuth) { const url = `${process.env.VUE_APP_APIPATH}/api/user/check`; axios.post(url).then((response) => { if (response.data.success) { next(); } else { store.dispatch('updateMessage', { message: `登入失敗惹Σ( ° △ °|||)︴${response.data.message}`, status: 'danger', }); next({ path: '/login', }); } }); } else { next(); } });
|
那麼該如何透過 router 來修改 title 呢?只需要在想要變換 title 的 meta 加入 title 即可
1 2 3 4 5 6 7
| const router = { meta: { title: '我要變 title', requiresAuth: true }, },
|
最後在針對導航守衛添加以下程式碼即可
1 2 3 4 5
| router.beforeEach((to, from, next) => { if (to.meta.title) { document.title = to.meta.title; } }
|
實際的效果你可以在 RagnarokShopV3看到,例如:首頁切換到關於、訂單以及商品等頁都有動態切換 title 的效果。
但其實這邊這個做法有一個問題,當若你在當前畫面下重新整理的話,那麼就會變回預設的 title。
因此在這邊若想要使用該方法的話,可以使用 localStorage 來解決該問題,只需要將導航守衛加入 localStorage
1 2 3 4 5 6
| router.beforeEach((to, from, next) => { if (to.meta.title) { document.title = to.meta.title; localStorage.setItem('title', to.meta.title); } }
|
並在實例化 Vue 時,使用生命週期 created 判斷是否有 title,若存在就寫入
1 2 3 4 5 6 7 8 9 10 11
| new Vue({ router, store, created() { const title = localStorage.getItem('title') || ''; if (title) { document.title = title; } }, render: (h) => h(App), }).$mount('#app');
|
這樣子就完美的解決在當前頁面下重新整理畫面會導致 title 跳回預設的問題。
GitHub Repositories

另一個方法則是使用 Vue Meta 套件
只要你安裝這個套件,並在每一個 .vue 檔案下建立一個 metaInfo 並將 title 寫入就可以了
1 2 3 4 5
| export default { metaInfo: { title: '六腳音樂大舞台', }, },
|
當然這套件也可以修改 lang 等等,可以透過官方文件看到
1 2 3 4 5 6 7 8 9 10
| export default { metaInfo: { title: 'My Example App', titleTemplate: '%s - Yay!', htmlAttrs: { lang: 'en', amp: true } } }
|
但是這邊卻有一個問題,若頁面較多時,那麼有幾頁要設置就變成要寫幾次,因此就會非常難以維護,因此這邊一樣可以透過 vue router 的 meta 做法來解決,雖然還是要在特定要修改的頁面加入相關參數,但這邊我們可以將相關 function 寫在 store 當作狀態管理
只是這邊要注意 metaInfo 必須改寫成一個 function
1 2 3 4 5
| metaInfo() { return { title: this.metaTitle, }; },
|
而 Vuex 部分只需要這樣即可
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20
| export default new Vuex.Store({ state: { metaTitle: '', }, mutations: { SETTITLE(state, payload) { state.metaTitle = payload; }, }, actions: { getMetaTitle(context, title) { context.commit('SETTITLE', title); }, }, getters: { metaTitle(state) { return state.metaTitle; }, }, });
|
實際應用的頁面則只需要這樣改即可
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22
| export default { data() { return { }; }, metaInfo() { return { title: this.metaTitle || 'HexfootMusic', }; }, methods: { getTitle() { this.$store.dispatch('getMetaTitle', this.$route.meta.title); }, }, computed: { ...mapGetters(['metaTitle']), }, async created() { this.getTitle(); }, };
|
那麼這樣的做法在於未來若我們要修改 title 的時候就只需要專注於 router 的 meta 即可。
實際應用可以看 HexfootMusic
GitHub Repositories
懶人的極致方法
最後這個方式也是最懶人的方式,堪稱接近無腦了,簡單來講就是直接在最上層的 App.vue 寫入判斷即可。
一樣我們在 Router 裡面寫入相關 meta title
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15
| const routes = [ { path: '/', name: '', component: () => import('../views/Layout.vue'), children: [ { path: '', name: 'Index', component: () => import('../views/Index.vue'), meta: { title: '全馬鐵人搜尋器首頁', }, }, ...
|
最後一步只需要在 App.vue 中寫入一個 watch 監聽 $route 變化
1 2 3 4 5 6 7 8 9
| @Component({ name: 'App', watch: { $route(to) { const nowTitle = to.meta.title || 'W3HexSchool 全馬鐵人搜尋器'; document.title = nowTitle; }, }, })
|
透過這種方式就算重新整理,也會被立刻修改 title 囉~
實際應用可以參考 W3HexSchool 全馬鐵人搜尋器
GitHub Repositories
參考文獻
整理這些技術筆記真的很花時間,如果你願意 關閉 Adblock 支持我,我會把這份感謝轉換成更多「踩坑轉避坑」的內容給你!ヽ(・∀・)ノ
Advertisement