主结构
/home /about /user/profile /user/posts
+------------------+ +-----------------+ +------------------+ +-----------------+
| Home | | About | | User | | User |
| +--------------+ | | +-------------+ | | +--------------+ | | +-------------+ |
| | | | +------------> | | | | +------------> | | UserProfile | | +------------> | | UserPosts | |
| | | | | | | | | | | | | | | |
| +--------------+ | | +-------------+ | | +--------------+ | | +-------------+ |
+------------------+ +-----------------+ +------------------+ +-----------------+
App.vue
<template>
<div id="app">
<div id="nav">
<router-link to="/">Home</router-link> |
<router-link to="/about">About</router-link> |
<router-link to="/user">User</router-link>
</div>
<router-view/>
</div>
</template>
<style>
#app {
font-family: Avenir, Helvetica, Arial, sans-serif;
-webkit-font-smoothing: antialiased;
-moz-osx-font-smoothing: grayscale;
text-align: center;
color: #2c3e50;
}
#nav {
padding: 30px;
}
#nav a {
font-weight: bold;
color: #2c3e50;
}
#nav a.router-link-exact-active {
color: #42b983;
}
.user a.router-link-exact-active.router-link-active {
color: #42b983;
}
.home h1 {
color: #42b983;
}
.user h1 {
color: orange
}
</style>
router/index.js
import Vue from 'vue'
import VueRouter from 'vue-router'
Vue.use(VueRouter)
const routes = [
// Home.vue
{
path: '/',
name: 'home',
component: () => import( '../views/Home.vue')
},
// About.vue
{
path: '/about',
name: 'about',
component: () => import('../views/About.vue')
},
// User.vue
{
path: '/user',
name: 'user',
component: () => import('../views/User.vue'),
// 嵌套 UserProfile.vue、 UserPosts.vue
children: [
{
path: '/profile',
component: () => import('../views/UserProfile.vue')
},
{
path: '/posts',
component: () => import('../views/UserPosts.vue')
}
]
}
]
const router = new VueRouter({
mode: 'history',
base: process.env.BASE_URL,
routes
})
export default router
src/main.js
import Vue from 'vue'
import App from './App.vue'
import router from './router'
import store from './store'
Vue.config.productionTip = false
new Vue({
router,
render: function (h) { return h(App) }
}).$mount('#app')
Home.vue
<template>
<div class="home">
<H1>This is an home page</H1>
</div>
</template>
<script>
export default {
name: 'Home',
}
</script>
About.vue
<template>
<div class="about">
<h1>This is an about page</h1>
</div>
</template>
User.vue
<template>
<div class="user">
<H1>This is an user page</H1>
<router-link to="profile">UserProfile</router-link> |
<router-link to="posts">Userposts</router-link>
<router-view />
</div>
</template>
<script>
export default {
name: 'User',
}
</script>
UserProfile.vue
<template>
<div class="profile">
<H2>This is an UserProfile page</H2>
</div>
</template>
UserPosts.vue
<template>
<div class="posts">
<H2>This is an UserPosts page</H2>
</div>
</template>
全局前置守卫
const router = new VueRouter({ ... })
router.beforeEach((to, from, next) => {
/* 比如做登陆验证
if (to.name !== 'Home' && !isAuthenticated) next({ name: 'Home' })
else next()
*/
document.title = to.matched[0].name
next()
})
全局后置钩子
router.afterEach((to, from) => {
// 注册全局后置钩子,这些钩子不会接受 next 函数也不会改变导航本身
// ...
})
路由独享守卫
// 你可以在路由配置上直接定义 beforeEnter 守卫:
const router = new VueRouter({
routes: [
{
path: '/Home',
component: () => import( '../views/Home.vue'),
beforeEnter: (to, from, next) => {
// ...
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`
}
}
beforeRouteEnter
/*
beforeRouteEnter 守卫 不能 访问 this,因为守卫在导航确认前被调用,因此即将登场的新组件还没被创建。
不过,你可以通过传一个回调给 next来访问组件实例。在导航被确认的时候执行回调,并且把组件实例作为回调方法的参数
*/
beforeRouteEnter (to, from, next) {
next(vm => {
// 通过 `vm` 访问组件实例
})
}
/* 注意
beforeRouteEnter 是支持给 next 传递回调的唯一守卫。对于 beforeRouteUpdate 和 beforeRouteLeave 来说,
this 已经可用了,所以不支持传递回调,因为没有必要了。
*/
beforeRouteUpdate
beforeRouteUpdate (to, from, next) {
// just use `this`
this.name = to.params.name
next()
}
beforeRouteLeave
beforeRouteLeave (to, from, next) {
const answer = window.confirm('Do you really want to leave? you have unsaved changes!')
if (answer) {
next()
} else {
next(false)
}
}
// 这个离开守卫通常用来禁止用户在还未保存修改前突然离开。该导航可以通过 next(false) 来取消
完整的导航流程
导航被触发。
在失活的组件里调用 beforeRouteLeave 守卫。
调用全局的 beforeEach 守卫。
在重用的组件里调用 beforeRouteUpdate 守卫 (2.2+)。
在路由配置里调用 beforeEnter。
解析异步路由组件。
在被激活的组件里调用 beforeRouteEnter。
调用全局的 beforeResolve 守卫 (2.5+)。
导航被确认。
调用全局的 afterEach 钩子。
触发 DOM 更新。
调用 beforeRouteEnter 守卫中传给 next 的回调函数,创建好的组件实例会作为回调函数的参数传入。
路由元信息
/*
定义路由的时候可以配置 meta 字段,分别给Home.vue加入路由元素 meta: { requiresAuth: true } ,
给About.vue加入路由元素 meta: { requiresAuth: false}
*/
const routes = [
{
path: '/',
name: 'Home',
component: () => import( '../views/Home.vue'),
meta: { requiresAuth: true }
},
// About.vue
{
path: '/about',
name: 'About',
component: () => import('../views/About.vue'),
meta: { requiresAuth: false}
},
// Login.vue
{
path: '/login',
name: 'Login',
component: () => import( '../views/Login.vue'),
}
]
// 全局前置守卫 判断 requiresAuth 的状态 ,false 跳转登陆页
router.beforeEach((to, from, next) => {
// console.log('from------从那个路由') console.log(from)
// console.log('to--------跳转到那个路由') console.log(to)
if(to.fullPath !== '/login' && !to.matched[0].meta.requiresAuth) next('login')
else next()
})
keep-alive
include 、exclude
<template>
<div id="app">
<div id="nav">
<router-link to="/">Home</router-link> |
<router-link to="/about">About</router-link>
</div>
<keep-alive exclude="About" include="Home,User">
<router-view />
</keep-alive>
</div>
</template>
// 本页:App.vue
// include 值为组件中的name、include 标记的组件会缓存
// exclude 值为组件中的name、exclude 标记的组件不会缓存
deactivated、deactivated
<template>
<div class="home">
<H1>This is an home page</H1>
</div>
</template>
export default {
name: 'Home',
components: {
},
data(){
return {
path :'/news'
}
},
mounted(){
console.log(this.$route.query)
},
method: {
},
create(){
console.log('-----------------------------Home created 创建')
},
destroyed(){
console.log('---------------------------Home destroyed 销毁')
},
activated(){
//活跃的
console.log('---------------------------Home activated活跃' + this.path)
this.$router.push(this.path)
},
deactivated(){
//不活跃的
console.log('---------------------------Home deactivated不活跃' + this.path)
},
beforeRouteLeave (to, from, next){
//前置导航,页面离开时执行
this.path = this.$route.path
next()
}
}
// 只有使用keep-alive时 才会调用 activated() deactivated()