Vue.js
本章內容:
路由
根據不同的路徑 (錨點) ,顯示不同的頁面 (組件) ,不會刷新整個頁面,,局部更新。
官方地址: https://router.vuejs.org/zh/
引入vue-router
<script src="https://unpkg.com/vue-router/dist/vue-router.js"></script>
vue-router提供的組件
router-view
路由的出口,用於渲染當前路由模板,在含有導航鏈接的頁面都與要進行路由出口,否則路由不起作用。
<router-link to="/Home">首頁</router-link> <!-- 導航鏈接 -->
<router-view></router-view> <!-- 路由出口 -->
router-link
導航鏈接
<router-link to="/Home">首頁</router-link>
-
標籤屬性
-
to (必選參數)
<router-link to="/Login">登錄</router-link> <!-- 表示路由的鏈接, 該值可以是字符串, 可也動態綁定數據 -->
-
tag
<router-link to="/Login" tag="strong">登錄</router-link> <!-- tag表示渲染成指定的標籤, 同樣還會監聽點擊, 觸發路由鏈接。默認是<a></a>標籤。 -->
-
定義路由
// 創建`router`實例,傳入`routes`配置。
let router = new VueRouter({
routes: [
{
path: "/index",
component: { // 每個路由中`component`的應該映射一個組件。
template: `<h3>首頁</h3>`
}
},
{
path: "/login",
component: {
template: `<h3>登錄</h3>`
}
}
]
})
new Vue({
el: "#app",
router // 將`router`掛載Vue實例中。
})
動態路由
例如,我們有一個 login
組件,對於所有 ID 各不相同的用戶,可以使用動態路由
將用戶ID傳入。
<div id="app">
<router-link to="/index">首頁</router-link>
<!-- 傳入用戶信息 -->
<router-link to="/login/1/狗蛋/12345678">登錄</router-link>
<router-view/> <!-- 路由出口 -->
</div>
// 創建`router`實例,傳入`routes`信息,並定義動態路由。
let router = new VueRouter({
routes: [
{
path: "/index",
component: {
template: `<h3>首頁</h3>`
}
},
{
path: "/login/:userID/:userName/:passWord", // 綁定動態路徑參數,以:進行綁定某些字段。
component: {
template: `<h3>{{$route.params}}</h3>`
}
}
]
})
new Vue({
el: "#app",
router // 掛載路由
})
命名路由
命名路由指的是在每一個路由配置上,都必須提供一個name
。
const Index = {
template: "..."
}
let router = new VueRouter({
routes: [
{
name: "index", // 提供當前路由配置上的`name`。
path: "/index",
component: Index
}
]
})
$router和$route的區別
-
$router爲VueRouter的實例, 是一個全局的路由對象。
-
$route是一個跳轉的路由對象, 每一個路由都有
route
對象, 是一個局部對象, 包含路由路徑
攜帶的參數,以及查詢字符攜帶
的參數。<div id="app"> <!-- 查詢參數 --> <router-link to="/index?userID=1&userName=大錘&passWord=1314521">首頁</router-link> <!-- 動態參數 --> <router-link to="/login/33/狗蛋/5211314">登錄</router-link> <router-view></router-view> <!-- 路由出口 --> </div>
let router = new VueRouter({ routes: [ { path: "/index", // 查詢參數不需要綁定。 component: { template: ` <div> <h3>登錄</h3> <h4>查詢參數爲:{{$route.query}}</h4> </div> ` } }, { path: "/login/:userID/:userName/:passWord", // 綁定動態路徑參數,以:進行綁定某些字段。 component: { template: ` <div> <h3>登錄</h3> <h4>動態參數爲:{{$route.params}}</h4> </div> ` } } ] }) new Vue({ el: "#app", router // 掛載`router`實例 })
嵌套路由
路由套路由,<router-view/>
內嵌套另一個<router-view/>
組件。
<div id="app">
<router-link to="/index">首頁</router-link>
<router-link to="/login">登錄</router-link>
<router-view></router-view> <!-- 路由出口 -->
</div>
let router = new VueRouter({
routes: [
{
path: "/index",
component: {
template: `
<div>
<h3>首頁</h3>
<router-link to="/index/child1">一入口</router-link>
<router-link to="/index/child2">二入口</router-link>
<router-link to="/index/child3">三入口</router-link>
<router-view></router-view>
</div>
`
},
children: [ // 配置index的子路由。
{
path: "child1",
component: {
template: `<h3>一入口</h3>`
}
},
{
path: "child2",
component: {
template: `<h3>二入口</h3>`
}
},
{
path: "child3",
component: {
template: `<h3>三入口</h3>`
}
}
]
},
{
path: "/login",
component: {
template: `<h3>登錄</h3>`
}
}
]
})
new Vue({
el: "#app",
router: router // 將配置的路由實例掛載Vue實例中。
})
路由重定向
例如我們訪問/a
路由,重定向規定爲/b
,則當訪問/a
就會切換到/b
路由。
let router = new VueRouter({
routes: [
{
path: "/", // `/`表示根目錄,`*`會匹配任意路由路徑。
redirect: "/index" // 定義重定向,如果是根目錄則自動重定向到`redirect`指定的路由。
},
{
path: "/index",
component: {
template: "<h3>首頁</h3>"
}
},
{
path: "/login",
component: {
template: "<h3>登錄</h3>"
}
}
]
})
編程式的導航
在Vue實例內部,你可以通過$router
訪問路由實例,因此你可以調用this.$router.push(...)
來導航到不同的路由。
或者使用 router.push
方法。這個方法會向 history 棧添加一個新的記錄,所以,當用戶點擊瀏覽器後退按鈕時,則回到之前 的 URL。
router是router實例掛載Vue實例之後自動生成的對象。而router是構造函數。
// 實例化router
let router = new VueRouter({
routes: []
})
new Vue({
el: "#app",
methods: {
routerFn() {
// $router是`router`實例掛載到Vue中才有的實例對象。
this.$route.push(...);
// router實例。
router.push(...);
console.log(router === this.$router); // true,兩種效果等效,都可使用。
}
},
router // 掛載`router`實例
})
-
push
該方法參數可以是一個字符串路徑,或者是一個敘述地址的對象。例如:// 字符串 this.$router.push("/index"); // 對象 this.$router.push({path: "index"}); // 命名路由,通過路由內配置的`name`值相互綁定,也可實現路由跳轉。 this.$router.push({name: "index"}); // params動態路由 this.$router.push({name: "index", params: {id: 1} }); // -> {id: 1},可以通過$route.params獲取。 // 查詢參數,URL變成 /index?id=100 this.$router.push({name: "index", query: {id: 100} }); // -> {id: 100},可以通過$route.query獲取。
如果提供了path,params就會被忽略,而
query
不會被忽略。你可以提供路由的name
或手寫完整的帶有參數的path
。const Id = '123'; // 提供了name,有效。 this.$router.push({name: "index", params: {Id} }); // -> /user/123 // 提供完整的`path`。 this.$router.push({ path: `/user/${Id}` }) // -> /user/123 // 這裏的params不生效。 this.$router.push({path: "index", params: {Id} });
-
go
這個方法的參數是一個整數,意思是在 history 記錄中向前或者後退多少步,類似window.history.go(n)
。// 在瀏覽器記錄中前進一步,等同於 history.forward()。 this.$router.go(1); // 後退一步記錄,等同於 history.back()。 this.$router.go(-1); // 前進 3 步記錄 this.$router.go(3); // 如果 history 記錄不夠用,那就默默地失敗唄 this.$router.go(-100); this.$router.go(100);
過渡動效
<router-view/>
是動態組件,所以我們可以使用<transition/>
組件給它添加一些過渡效果。
<transition name="fade">
<router-view></router-view>
</transition>
單個路由的過渡
上面語法是給所有出口都進行了相同的過渡,如果想給每個路由模板添加各自的效果,可以在<transition/>
上定義不同的name
。
const Bar = {
template: `
<transition name="fade">
<div>...</div>
</transition>
`
}
const Foo = {
template: `
<transition name="slide">
<div>...</div>
</transition>
`
}
導航守衛
vue-router
提供的導航守衛主要用來通過跳轉或阻止跳轉的方式守衛導航。記住參數或查詢的改變並不會觸發進入/離開的導航守衛
全局前置守衛
使用router.beforeEach
來註冊一個全局前置守衛。
let router = new VueRouter({
routes: [
// ...
]
})
router.beforeEach((to, from, next) => {
// ...
})
同樣也可以在vue中掛載的路由實例進行註冊導航守衛。
let router = new VueRouter({
routes: [
// ...
]
})
new Vue({
el: "#app",
router, // ES6語法,與router: router等效
mounted() {
// 通過路由實例註冊
this.$router.beforeEach((to, from, next) => {
// ...
})
}
})
-
每個守衛方法接受三個參數:
-
to
即將要進入的目標路由。 -
from
即將要離開的當前路由。 -
next
用於允許路由的切換,在路由切換中必須調用next()
, 否則鉤子就不會被調用。router.beforeEach((to, from, next) => { next(); // 進行管道中的下一個鉤子 next(false); // 中斷當前的導航 next({path: "/login"}) // 鏈接到指定的路由,與`next("/login")`等效 })
-
全局後置守衛
使用router.afterEach
來註冊一個全局後置守衛,但是它不接收next參數。
router.afterEach((to, from) => {
// ...
})
前置守衛與後置守衛的區別
路由獨享守衛
在路由配置上直接定義beforeEnter
守衛
let router = new VueRouter({
routes: [
{
path: "/index",
component: Index,
beforeEnter(to, from, next) {
// ...
}
}
]
})
組件內部守衛
在路由組件內直接定義以下路由導航守衛 :
const Foo = {
template: `...`,
beforeRouteEnter (to, from, next) {
// 在渲染該組件的對應路由被 confirm 前調用
// 不!能!獲取組件實例 `this`
// 因爲當守衛執行前,組件實例還沒被創建
},
beforeRouteUpdate (to, from, next) {
// 在當前路由改變,但是該組件被複用時調用
// 舉例來說,對於一個帶有動態參數的路徑 /foo/:id,在 /foo/1 和 /foo/2 之間跳轉的時候,
// 由於會渲染同樣的 Foo 組件,因此組件實例會被複用。而這個鉤子就會在這個情況下被調用。
// 可以訪問組件實例 `this`
},
beforeRouteLeave (to, from, next) {
// 導航離開該組件的對應路由時調用
// 可以訪問組件實例 `this`
}
}