什么是VueRouter
Vue Router 是 Vue.js 官方的路由管理器。它和 Vue.js 的核心深度集成,讓構建單頁面應用變得易如反掌。
如何使用?
- 使用VueRouter至少需要引入vue-router和Vue。
import Vue from "vue";
import VueRouter from "vue-router";
- 初始化一個vuerouter對象,並在vue中注冊
const router = new VueRouter({
[ {
path: "/",
name: "Home",
component: Home
}]
});
Vue.use(VueRouter);
new Vue({
router,
store,
render: h => h(App)
}).$mount("#app");
3.初始化vuerouter對象時需要定義router路由配置,當路由命中時,vuerouter會將組件加載到頁面上。
通過腳手架創建的Vue項目的vueRouter使用實例
- 在mian.js中導入VueRouter,並注冊成全局屬性。示例中引入是router配置所在的文件夾,因為大型項目中,可能需要將router配置信息記錄到多個文件中,方便管理。
import Vue from "vue";
import App from "./App.vue";
import router from "./router";
Vue.config.productionTip = false;
Vue.use(Button);
new Vue({
router,
store,
render: h => h(App)
}).$mount("#app");
- 在router文件夾中,我們創建一個index.js文件,用來放置router的相關配置。
import Vue from "vue";
import VueRouter from "vue-router";
import Home from "../views/Home.vue";
import NotFound from "../views/404";
Vue.use(VueRouter);
const routes = [
{
path: "/",
name: "Home",
component: Home
},
{
path: "/about",
name: "About",
// route level code-splitting
// this generates a separate chunk (about.[hash].js) for this route
// which is lazy-loaded when the route is visited.
component: () =>
import(/* webpackChunkName: "about" */ "../views/About.vue")
},
{
path: "*",
name: "404",
component: NotFound
}
];
const router = new VueRouter({
mode: "history",
base: process.env.BASE_URL,
routes
});
export default router;
- 短短兩步,我們已經有了一個可以home,ablout以及404之間切換的路由了。
vueRouter配置文件詳解
index.js中的相關配置代碼有幾個地方需要說明:
- 首先需要引入vue和vue-router,這是一切的基礎。
import Vue from "vue";
import VueRouter from "vue-router";
- 其次需要告知Vue使用vue-router
Vue.use(VueRouter);
- 定義一個新的VueRouter,並export到外面,方便在mian.js中的new Vue中注冊。
const router = new VueRouter({
mode: "history",
base: process.env.BASE_URL,
routes
});
export default router;
- new VueRouter有三個參數。
- mode代表路由模式,它的默認值是hash模式,hash模式很丑,且不支持錨定向,所以如果希望有個漂亮的路由或支持錨定向,可以考慮使用history模式。具體的區別可以查看官方文檔。
- base代表應用的基路徑,process.env.BASE_URL是指從從環境進程中根據運行環境獲取的api的base_url
- routes 則是具體的路由配置列表,這個參數最核心也最關鍵
routes數組的詳細配置
在routes數組中,每一個元素都是一個Router對象。
如下配置,是指當瀏覽器的路由地址是web站點(准確的說是單體應用)根目錄時,我們將要觸發的路由,它的名字叫Home,它將為系統掛接Home組件。
{
path: "/",
name: "Home",
component: Home
},
<router-view />
和<router-link/>
組件
Home組件將被掛接到什么位置?我們可以查看我們的入口組件APP.vue;觸發Home路由時,Vue會幫我們將Home組件掛接到
Vue還為我們提供了router-link組件切換我們的路由地址,只需要在to的位置制定路由的地址(即path)即可。
//app組件
<template>
<div id="app">
<div id="nav">
<router-link to="/dashboard/analysis">Home</router-link> |
<router-link to="/form">form</router-link>
</div>
<router-view />
</div>
</template>
<style lang="less"></style>
//home組件
<template>
<div class="home">
this is Home
</div>
</template>
<script>
// @ is an alias to /src
export default {
name: "Home",
components: {}
};
</script>
效果如下:
上述方式非常簡單的將我們的Home組件和我們路由地址"/"進行了掛接,但是這種方式有一個缺點:我們需要在頭部先引入這個home組件,Vue才能找到。
import Home from "../views/Home.vue";
有沒有更簡單的方式,不用每次將組件明確的導入呢?
路由懶加載
有更簡單的方式:采用component動態注入(路由懶加載),即示例中about的掛接方式。如下配置,是指當瀏覽器的路由地址是web站點(准確的說是單體應用)根目錄+"/about"時,我們將要觸發的路由,它的名字叫About,它將為系統掛接views目錄下的About.vue組件
{
path: "/about",
name: "About",
// route level code-splitting
// this generates a separate chunk (about.[hash].js) for this route
// which is lazy-loaded when the route is visited.
component: () =>
import(/* webpackChunkName: "about" */ "../views/About.vue")
},
component后的內容是一個ES6的箭頭函數寫法,它的意思是將這個路由打包在一個叫about的異步塊中,並加載../views/About.vue這個組件。通過這種方式既可以動態加載組件,又可以提升組件的加載速度(只加載當前要用的異步塊中組件)
() =>
import(/* webpackChunkName: "about" */ "../views/About.vue")
效果如下
404路由的配置
很多時候,我們需要在用戶將路由地址輸入錯誤后,帶領用戶進到404頁面。
VueRouter的解決方案是通配符;代表可以匹配所有的地址,我們將如下router類寫在routers數組的最后(順序一定不能錯,不然就會將用戶的正確地址帶到404),當用戶輸入的路由沒有被前面的所有路由匹配時可以觸發。觸發404路由時,我們掛接NotFound組件。
import NotFound from "../views/404";
{
path: "*",
name: "404",
component: NotFound
}
效果如下
嵌套路由的配置
我們剛剛一直都只講了單層路由,但是實際項目過程中,路由是非常復雜了,路由地址的層級可能非常深。那么對於這種情況?vueRouter如何處理?
先看如下代碼:
{
path: "/user",
component: () =>
import(/* webpackChunkName: "layout" */ "../layouts/UserLayout"),
children: [
{
path: "/user",
redirect: "/user/Login"
},
{
path: "/user/login",
name: "login",
component: () =>
import(/* webpackChunkName: "user" */ "../views/User/Login")
},
{
path: "/user/register",
name: "register",
component: () =>
import(/* webpackChunkName: "user" */ "../views/User/Register")
}
]
},
我們只需要未router對象增加children數組即可,children數組里面依然是一組router對象,每一個Router對象還可以有自己的chilfren。
{
path: "/dashboard",
component: () =>
import(/* webpackChunkName: "layout" */ "../layouts/BasicLayout"),
children: [
{
path: "/dashboard",
redirect: "/dashboard/analysis"
},
{
path: "/dashboard",
name: "dashboard",
component: { render: h => h("router-view") },
children: [
{
path: "dashboard/analysis",
name: "analysis",
component: () =>
import(
/* webpackChunkName: "dashboard" */ "../views/Dashboard/Analysis"
)
}
]
}
]
},
嵌套路由的注意事項
上述示例中需要注意以下幾點
- 擁有children屬性的組件,必須要在template中定義
指定子路由中的組件掛接的位置。如BasicLayout組件中應定義router-view占位,保證它的子路由組件會掛接到占位位置。利用這個特性完成在BasicLayout中做一些樣式和布局處理
//BasicLayout.vue
<template>
<div>
<Header></Header>
<SiderMenu></SiderMenu>
<router-view></router-view>
<Footer></Footer>
</div>
</template>
<script>
import Header from "./Header";
import Footer from "./Footer";
import SiderMenu from "./SiderMenu";
export default {
components: {
Header,
Footer,
SiderMenu
}
};
</script>
<style></style>
- 但是如果我的父路由的組件沒有布局或樣式,僅僅只是顯示子路由的組件內容,專門創建一個組件並標記
,很浪費,我們可以采用component: { render: h => h("router-view") },的方式動態注冊
{
path: "/dashboard",
name: "dashboard",
component: { render: h => h("router-view") },
children: [
{
path: "dashboard/analysis",
name: "analysis",
component: () =>
import(
/* webpackChunkName: "dashboard" */ "../views/Dashboard/Analysis"
)
}
]
}
路由重定向
在部分場景下,我們希望能重定向某些路由地址。vueRouter提供了關鍵字redirect專門處理這些問題,如上述例子中的user,在匹配路由/user時,本來應該掛接UserLayout組件,但是我們通過redirect,將/user重定向到/user/Login了
{
path: "/user",
component: () =>
import(/* webpackChunkName: "layout" */ "../layouts/UserLayout"),
children: [
{
path: "/user",
redirect: "/user/Login"
},
{
path: "/user/login",
name: "login",
component: () =>
import(/* webpackChunkName: "user" */ "../views/User/Login")
}
]
},
路由守衛
我們在路由切換過程中可能需要自定義某些事件處理某些業務邏輯,vueRouter提供了路由守衛模塊。
譬如,我們假設希望在路由切換時調用頁面加載進度條,我們可以先引用nprogress以及其樣式(需要額外安裝),然后我們通過vueRouter提供的beforeEach和afterEach來觸發
import Nprogress from "nprogress";
import "nprogress/nprogress.css";
router.beforeEach((to, form, next) => {
//開始轉跳,加載Nprogress進度條
Nprogress.start();
next();
});
router.afterEach(() => {
//轉跳結束,Nprogress進度條加載完畢
Nprogress.done();
});
最近在自學Vue,跟着唐金州老師的視頻課程,一邊聽,一邊練,一邊總結思考,形成了如下內容,歡迎大家指正批評。