在nuxt中使用路由重定向的實例
我們都知道,在寫SPA的時候,我們可以通過配置vue-router來實現(xiàn)路由的重定向。
官方文檔(以及ts類型)的定義中給出了這一選項:
interface RouteConfig = {
path: string,
redirect?: string | Location | Function,
}
也就是說,我們可以定義這樣一個路由:
{
path: "/foo",
redirect: "/foo/bar",
}
這樣,我們在訪問/foo的時候,就會被重定向到/foo/bar。這些都是老生常談了。
然而,到了SSR的環(huán)境下,如果使用nuxt,因為nuxt采用了約定大于配置的方式,pages目錄代替了路由,雖然簡化了配置,但是給一些需要定制化的場景的手動配置帶來了一些麻煩,并且nuxt官方也不建議手動配置router,如果實在需要配置,可以在nuxt.config.js里進行一些中間件配置,但是這個對于重定向這種特別簡單的事情來說,未免有殺雞用牛刀之嫌。
所以,我一開始想的辦法是,在pages目錄下,需要重定向的路由組件里,增加一個beforeCreate()鉤子:
<template>
<div></div>
</template>
<script>
export default {
beforeCreate() {
this.$router.replace('/path/to')
}
}
</script>
相當于在組件創(chuàng)建之前進行一個路由的替換,這個組件作為路由的占位。之所以不用push而是用replace,因為replace更接近重定向的效果,我們總不希望用戶還能回退(比如瀏覽器的后退鍵)到重定向之前的頁面里去吧。
但是這個方案有一個問題,就是在路由“重定向”的過程中,界面會發(fā)生輕微的閃爍,這樣體驗就很不好了。所以,肯定需要其他的解決方案。
至于為什么會閃屏,因為雖然beforeCreate鉤子理論上會先于模板編譯執(zhí)行,但是這是在SFC環(huán)境下,模板編譯會提前執(zhí)行;如果是用script標簽引入的Vue就不會有這個問題:
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<script src="https://unpkg.com/vue@2.6.11/dist/vue.js"></script>
<script src="https://unpkg.com/vue-router@3.1.6/dist/vue-router.js"></script>
</head>
<body>
<div id="app">
<router-view/>
</div>
<script>
const Foo = {template: '<div>foo</div>'};
const Bar = {template: '<div>bar</div>'};
const routes = [
{path: '/foo', component: Foo, redirect: '/bar'},
{path: '/bar', component: Bar}
];
const router = new VueRouter({routes});
const app = new Vue({
el: '#app',
router
})
</script>
</body>
</html>
如果有需要,可以進一步參考Vue官方的生命周期圖示。
查了一下文檔,好在nuxt提供了這么一個重定向的API,就藏在context對象里。事實上,下面所有的解決方案,都是基于這個context對象進行的:
| 屬性字段 | 類型 | 可用 | 描述 |
|---|---|---|---|
| redirect | Function | 客戶端 & 服務端 | 用這個方法重定向用戶請求到另一個路由。狀態(tài)碼在服務端被使用,默認 302 redirect([status,] path [, query]) |
同時,我們還知道:
asyncData方法會在組件(限于頁面組件)每次加載之前被調(diào)用。它可以在服務端或路由更新之前被調(diào)用。在這個方法被調(diào)用的時候,第一個參數(shù)被設(shè)定為當前頁面的上下文對象,你可以利用 asyncData方法來獲取數(shù)據(jù)并返回給當前組件。
所以,我們可以這么寫:
<template>
<div></div>
</template>
<script>
export default {
asyncData({ redirect }) {
redirect('/path/to')
}
}
</script>
這樣就可以解決問題了??赡苣銜霝槭裁床挥胒etch來進行路由跳轉(zhuǎn),因為fetch是用來處理vuex store的數(shù)據(jù)的,我個人認為從語義上不適合處理路由跳轉(zhuǎn)的任務;當然,實際上是可以正常運行的,反正都是基于context對象進行的操作。
如果你對上面那個空的div感到不滿意,覺得不優(yōu)雅,你也可以搞得更極端一點,使用渲染函數(shù)來渲染模板的根節(jié)點:
<script>
export default {
asyncData({ redirect }) {
redirect('/path/to')
},
render(h) {
return h('div')
}
}
</script>
這樣看起來可能更簡潔一點。
但是這種寫法對于路由鑒權(quán)那種場景是不太適用的。比如,我需要在進行路由跳轉(zhuǎn)前驗證用戶的身份,我總不能在每個page里都寫這么一段吧,維護起來也不方便,如果路由改了,每個頁面都得改。
所以,這個時候就得用到nuxt提供的中間件機制了。中間件可以在page層面配置,也可以全局配置,參考官方的例子:
pages/secret.vue
<template>
<h1>Secret page</h1>
</template>
<script>
export default {
middleware: 'authenticated'
}
</script>
middleware/authenticated.js
export default function ({ store, redirect }) {
// If the user is not authenticated
if (!store.state.authenticated) {
return redirect('/login')
}
}
這個也放到nuxt.config.js里,變成全局的配置:
module.exports = {
router: {
middleware: 'authenticated'
}
}
但是有一點需要注意,也是只要使用路由就需要注意的一個問題:避免循環(huán)重定向。這和避免寫死循環(huán)是一個道理。
總結(jié)一下:
如果是少數(shù)幾個頁面之間的固定的重定向邏輯,可以直接用asyncData(或者fetch,雖然我個人覺得語義不好)參數(shù)里context的redirect來進行重定向;
如果需要重定向的頁面數(shù)量較多(可以考慮使用中間件 + 表驅(qū)動),或者存在一些動態(tài)變化的重定向邏輯(比如路由鑒權(quán)),可以考慮使用中間件機制。
補充知識:使用Nuxt.js和Vue-i18n重定向到同一頁面但切換語言URL
公司最近提出一個需求,就是當用戶切換語言的時候,在路由中需要將其選中的語言加入到路由中
例如網(wǎng)址:
localhost/about
應該通過該方法(通過按特定按鈕)重定向到:
localhost/bg/about
Nuxt文檔中所建議的,用于使用Vue-i18n進行本地化https://nuxtjs.org/examples/i18n/
在 Nuxt 官網(wǎng)中也給出了國際化的例子,但是并不滿足公司的這個需求,大家有興趣可以去看下
Nuxt 官網(wǎng) 國際化的例子
在 components文件夾下面新建 LangSelect.vue文件
<template>
<el-dropdown trigger="click" class="international" @command="handleSetLanguage">
<div>
<i class="el-icon-share">{{$t('home.changelang')}}</i>
</div>
<el-dropdown-menu slot="dropdown">
<el-dropdown-item :disabled="language==='zh'" command="zh">中文</el-dropdown-item>
<el-dropdown-item :disabled="language==='en'" command="en">English</el-dropdown-item>
</el-dropdown-menu>
</el-dropdown>
</template>
<script>
export default {
computed: {
language() {
return this.$store.state.locale;
}
},
methods: {
handleSetLanguage(language) {
this.$i18n.locale = language;
console.log(this.$i18n.locale);
this.$store.commit("SET_LANG", language);
// console.log(this.$store.state.locale, "locale");
var beforePath = this.$nuxt.$router.history.current.path;
// -- Removing the previous locale from the url
var changePath = this.$store.state.locale
var result = "";
result = beforePath.replace("/en", "");
result = result.replace("/zh", "");
this.$nuxt.$router.replace({ path: "/" + changePath + result });
this.$message({
message: "Switch Language Success",
type: "success"
});
}
}
};
</script>
在middleware文件中新建i18n.js
export default function ({ isHMR, app, store, route, params, error, redirect }) {
const defaultLocale = app.i18n.fallbackLocale
// If middleware is called from hot module replacement, ignore it
//如果從熱模塊替換調(diào)用中間件,請忽略它
if (isHMR) { return }
// Get locale from params
const locale = params.lang || defaultLocale
if (!store.state.locales.includes(locale)) {
return error({ message: 'This page could not be found.', statusCode: 404 })
}
// Set locale
store.commit('SET_LANG', locale)
app.i18n.locale = store.state.locale
if(route.fullPath == '/') {
return redirect('/' + defaultLocale + '' + route.fullPath)
}
}
其他的配置都可以在 上面給出的官網(wǎng)鏈接中找到,這里就不在重復了。
以上這篇在nuxt中使用路由重定向的實例就是小編分享給大家的全部內(nèi)容了,希望能給大家一個參考,也希望大家多多支持腳本之家。
相關(guān)文章
如何使用vue slot創(chuàng)建一個模態(tài)框的實例代碼
這篇文章主要介紹了如何使用vue slot創(chuàng)建一個模態(tài)框,本文通過實例代碼給大家介紹的非常詳細,具有一定的參考借鑒價值,需要的朋友可以參考下2020-05-05
詳解vue-cli項目中用json-sever搭建mock服務器
這篇文章主要介紹了詳解vue-cli項目中用json-sever搭建mock服務器,小編覺得挺不錯的,現(xiàn)在分享給大家,也給大家做個參考。一起跟隨小編過來看看吧2017-11-11
vue中element 的upload組件發(fā)送請求給后端操作
這篇文章主要介紹了vue中element 的upload組件發(fā)送請求給后端操作,具有很好的參考價值,希望對大家有所幫助。一起跟隨小編過來看看吧2020-09-09
vue中如何實現(xiàn)后臺管理系統(tǒng)的權(quán)限控制的方法示例
這篇文章主要介紹了vue中如何實現(xiàn)后臺管理系統(tǒng)的權(quán)限控制的方法示例,小編覺得挺不錯的,現(xiàn)在分享給大家,也給大家做個參考。一起跟隨小編過來看看吧2018-09-09

