# vue-router
# 起步
Home.vue
<template>
<div>
<h1>Home</h1>
</div>
</template>
2
3
4
5
App.vue
<template>
<div id="app">
<router-link to = "/home" replace>首页</router-link>
<router-view></router-view>
</div>
</template>
2
3
4
5
6
index.js
import Home from "../components/User";
Vue.use(Router)
export default new Router({
routes: [
{
path: '/home',
name: 'home',
component: Home,
}
]
})
2
3
4
5
6
7
8
9
10
11
# 路由重定向
使用redirect
默认将Home设为首页
index.js
routes: [
{
path: '/',
redirect:'/home'
},
{
path: '/home',
name: 'home',
component: Home,
}
]
2
3
4
5
6
7
8
9
10
11
# Hash与History模式
vue-router默认hash模式, ur使用 # 后面定位路由,对seo不利,设置history,就可以使用普通的url模式
history模式即普通url模式,这种模式充分利用history.pushState API来完成URL跳转而无须重新加载页面
# 修改为history模式
export default new Router({
routes: [
{
path: '/home',
name: 'home',
component: Home,
}
],
mode:'history' //加入属性history
})
2
3
4
5
6
7
8
9
10
# router-link
<router-link to = "/home" replace>首页</router-link>
# router-link 其他属性
- tag
tag属性可以更改router-link的渲染的组件
<router-link to = "/home" tag="button">首页</router-link>
- replace
设置不能返回
<router-link to = "/home" tag="button" replace>首页</router-link>
- router-link-active
路由匹配成功时,会自动给当前元素设置一个router-link-active
的class
例如设置点击变色
.router-link-active{
color: cornflowerblue;
}
2
3
# 通过代码跳转路由
通过$router.push
跳转
HTML
<button @click = "homeClick">首页</button>
JS
methods:{
homeClick(){
this.$router.push('/home').catch(err=>{err})
}
}
2
3
4
5
# 动态路由
可以接收参数数据的路由形式,路由地址的一部分是会发生变化的
# 1. 通过$route.params
传递参数
App.vue
HTML
<router-link :to = "'/user/'+userId" replace>我</router-link>
<router-view :my-name="userId"></router-view>
2
JS
data(){
return{
userId:'Okarin'
}
}
2
3
4
5
User.vue
HTML
<template>
<div>
<h3>{{userId}} is my name</h3>
</div>
</template>
2
3
4
5
JS
computed:{
userId(){
return this.$route.params.userId
}
}
2
3
4
5
index.js
{
path:'/user/:userId', //:后面接参数名字
name:'user',
component:User
}
2
3
4
5
# 2. 通过props
属性传递
App.vue
HTML
<router-view :my-name="userId"></router-view>
JS
data(){
return{
userId:'Okarin'
}
}
2
3
4
5
User.vue
HTML
<template>
<div>
<h1> Hello {{myName}}! </h1>
</div>
</template>
2
3
4
5
JS
props:{
myName:{
type:String,
dafult:'Retr0',
required:true
}
2
3
4
5
6
index.js
{
path:'/user/:userId', //:后面接参数名字
name:'user',
component:User
}
2
3
4
5
# 3. 通过query
属性传递
App.vue
HTML
<router-link :to ="{path:'/profile',query:{name:'Okarin',age:'18',words:'EL PSY CONGROO!' } }" replace>个人</router-link>
Profile.vue
HTML
<template>
<div>
<h1>{{profileInfo.name}}</h1>
<h2>Age: {{profileInfo.age}}</h2>
<h3>{{profileInfo.words}}</h3>
</div>
</template>
2
3
4
5
6
7
8
JS
computed:{
profileInfo(){
return this.$route.query
}
}
2
3
4
5
# 通过代码跳转传递参数
App.vue
HTML
<button @click = "profileClick">我的</button>
JS
profileClick() {
this.$router.push({
path:'/profile',
query:{
name:'retr0',
age:'19',
words:'let us coding!' }
})
}
2
3
4
5
6
7
8
9
# 路由懒加载
分组件打包js
index.js
const Home = () => import( "../components/Home");
// import Home from "../components/User"; 对比
2
# 嵌套路由
index.js
{
path: '/home',
name: 'home',
component: Home,
children:[
{
path: '/',
redirect:'news'
},
{
path:'news',
component:HomeNews
},
{
path:'message',
component:HomeMessage
}
]
}
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
Home.vue
HTML
<template>
<div>
<h1>Home</h1>
<router-link to = "/home/news">新闻</router-link>
<router-link to = "/home/message">消息</router-link>
<router-view/>
</div>
</template>
2
3
4
5
6
7
8
# 全局导航守卫
可以用来做用户在没有登录注册时的拦截
使用 router.beforeEach
(前置钩子函数) 注册一个全局前置守卫:
const router = new VueRouter({ ... })
router.beforeEach((to, from, next) => {
// ...
})
2
3
4
5
每个守卫方法接收三个参数:
- to: Route: 即将要进入的目标 路由对象
- from: Route: 当前导航正要离开的路由
- next: Function: 一定要调用该方法来 resolve 这个钩子。执行效果依赖 next 方法的调用参数。
# 设置网页标题
index.js
{
path:'/about',
meta:{
title:'关于'
}, //使用meta元数据
name:'about',
component:About
}
router.beforeEach((to, from, next) => {
document.title = to.matched[0].meta.title
next()
})
2
3
4
5
6
7
8
9
10
11
12
13
14
15
# 全局守卫补充
- afterEach(后置钩子)
# 组件中的守卫
- beforeRouteEnter
- beforeRouteUpdate
- beforeRouteLeave
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`
}
}
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
# vue router 与 keep-alive
使用$route.meta的keepAlive属性:
<keep-alive>
<router-view v-if="$route.meta.keepAlive"></router-view>
</keep-alive>
<router-view v-if="!$route.meta.keepAlive"></router-view>
2
3
4
需要在router中设置router的元信息meta:
//...router.js
export default new Router({
routes: [
{
path: '/',
name: 'Hello',
component: Hello,
meta: {
keepAlive: false // 不需要缓存
}
},
{
path: '/page1',
name: 'Page1',
component: Page1,
meta: {
keepAlive: true // 需要被缓存
}
}
]
})
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
使用效果
以上面router的代码为例:
<!-- Page1页面 -->
<template>
<div class="hello">
<h1>Vue</h1>
<h2>{{msg}}</h2>
<input placeholder="输入框"></input>
</div>
</template>
2
3
4
5
6
7
8
<!-- Hello页面 -->
<template>
<div class="hello">
<h1>{{msg}}</h1>
</div>
</template>
2
3
4
5
6
(1) 在Page1页面输入框输入“asd”,然后手动跳转到Hello页面;
(2) 回到Page1页面发现之前输入的"asd"依然保留,说明页面信息成功保存在内存中;
当然,也可以通过动态设置route.meta的keepAlive属性来实现其他需求
首页是A页面
B页面跳转到A,A页面需要缓存
C页面跳转到A,A页面不需要被缓存
思路是在每个路由的beforeRouteLeave(to, from, next)
钩子中设置to.meta.keepAlive
:
A的路由:
{
path: '/',
name: 'A',
component: A,
meta: {
keepAlive: true // 需要被缓存
}
}
export default {
data() {
return {};
},
methods: {},
beforeRouteLeave(to, from, next) {
// 设置下一个路由的 meta
to.meta.keepAlive = true; // B 跳转到 A 时,让 A 缓存,即不刷新
next();
}
};
export default {
data() {
return {};
},
methods: {},
beforeRouteLeave(to, from, next) {
// 设置下一个路由的 meta
to.meta.keepAlive = false; // C 跳转到 A 时让 A 不缓存,即刷新
next();
}
};
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31