Vue Router 是 Vue.js 官方的路由管理器,是Vue三大核心插件之一,重中之重可见一斑。

前端路由实现

传统开发方式

url改变后,立刻发生请求响应整个页面,有可能资源过多,让页面出现白屏。

SPA单页应用

锚点值发生改变,不会立刻发送请求,而是在某个合适的时机,发起Ajax请求局部刷新

原生Js实现

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
<a href="/home">登录页面</a>
<a href="/user">注册页面</a>
<div id="app"></div>
<script>
window.onhashchange = function(){
console.log(location.hash);
switch (location.hash) {
case '#/home':
oDiv.innerHTML = '<h2>我首页</h2>';
break;
case '#/user':
oDiv.innerHTML = '<h2>我是用户页</h2>';
break;
default:
break;
}
}
</script>

VueRouter实现

使用路由

使用路由,就会创建router-link、router-view两个核心组件。

1
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
32
33
34
35
36
37
38
39
40
41
42
43
44
<div id="app"></div>
<script src="node_modules/vue/dist/vue.min.js"></script>
<script src="node_modules/vue-router/dist/vue-router.min.js"></script>
<script>
// 不需要Vue使用VueRouter创建,模块化开发中使用
// Vue.use(VueRouter)
const App = {
template: `
<div>
<router-link to="/login">登录</router-link>
<router-link to="/user">用户</router-link>
<router-view></router-view>
</div>
`

}
const Login = {
template: '<div>我是登陆页</div>'
}
const User = {
template: '<div>我是用户页</div>'
}
const router = new VueRouter({
routes: [{
path: '/login',
component: Login
}, {
path: '/user',
component: User
}]
})
new Vue({
el: '#app',
data() {
return {

}
},
components: {
App
},
router,
template: '<App />'
})
</script>

设置路由别名

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
const App = {
template: `
<div>
<router-link :to="{name: 'login'}">登录</router-link>
<router-link :to="{name: 'user'}">用户</router-link>
<router-view></router-view>
</div>
`

}
const router = new VueRouter({
routes: [{
path: '/login',
name: 'login',
component: Login
}, {
path: '/user',
name: 'user',
component: User
}]
})

路由参数的两种方式:params和query

1
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
const App = {
template: `
<div>
<router-link :to="{name: 'userP', params: {id: 1}}">用户1</router-link>
<router-link :to="{name: 'userQ', query: {userId: 2}}">用户2</router-link>
<router-view></router-view>
</div>
`

}
const userParams = {
template: '<div>我是用户1</div>'
}
const userQuery = {
template: '<div>我是用户2</div>'
}
const router = new VueRouter({
routes: [{
path: '/user/:id', // params范式
name: 'userP'
component: userParams
}, {
path: '/user', // query范式
name: 'userQ'
component: userQ
}]
})

路由对象访问

$route:当前路由信息对象;$router:全局路由实例对象,有go、push、replace等常用方法。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
const userParams = {
template: '<div>我是用户1</div>',
created(){
console.log(this.$router)
console.log(this.$route.params.id);
}
}
const userQuery = {
template: '<div>我是用户2</div>',
created(){
console.log(this.$router)
console.log(this.$route.query.userId);
}
}

路由嵌套

路由中设置chilren属性配置子路由,注意子路由的path路径不要出错

1
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
32
33
34
35
const Song = {
template: '<div>我是音乐</div>'
}
const Movie = {
template: '<div>我是电影</div>'
}
const Login = {
template: '<div>我是登录页</div>'
}
const User = {
template: `<div>
我是用户页<br>
<router-link to="/user/song">歌曲</router-link>
<router-link to="/user/movie">电影</router-link>
<router-view></router-view>
</div>`

}
const router = new VueRouter({
routes: [{
path: '/login',
name: 'login',
component: Login
}, {
path: '/user',
name: 'user',
component: User,
children: [{
path: 'song',
component: Song
}, {
path: 'movie',
component: Movie
}]
}]
})

缓存渲染keep-alive

切换路由的时候,把内容缓存起来,防止重复渲染和用户操作丢失。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
const Song = {
template: '<div @click="clickHandler">我是音乐</div>',
methods: {
clickHandler(e){
e.target.style.color = 'red';
}
}
}
const User = {
template: `<div>
我是用户页<br>
<router-link to="/user/song">歌曲</router-link>
<router-link to="/user/movie">电影</router-link>
<keep-alive>
<router-view></router-view>
</keep-alive>
</div>`

}

导航守卫

vue-router提供的导航守卫主要用来通过跳转或取消的方式守卫导航。比如你需要验证到登录信息后才能进入用户页,否则你将可能跳转到一个登录页面。

router.beforeEach(to, from, next) 在每个路由切换前都去进行监听判断,路由中的meta字段设置需要通过验证的标记。

1
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
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
const Login = {
data() {
return {
name: localStorage.getItem('user') && localStorage.getItem('user').name || '',
pwd: localStorage.getItem('user') && localStorage.getItem('user').pwd || ''
}
},
template: `<div>
<input type="text" :value="name" v-model="name" />
<input type="password" :value="pwd" v-model="pwd" />
<button @click="loginHandler">登录</button>
</div> `,

methods: {
loginHandler() {
localStorage.setItem('user', {
name: this.name,
pwd: this.pwd
})

//编程式路由(相对的是声明式路由)
this.$router.push({
name: 'user'
})

}
}
}
const User = {
template: '<div>我是用户页</div>'
}
const router = new VueRouter({
routes: [{
path: '/login',
name: 'login',
component: Login
}, {
path: '/user',
name: 'user',
component: User,
meta: {
auth: true
}
}]
})

router.beforeEach((to, from, next) => {
console.log('to', to);
console.log('from', from);
if (to.meta.auth) {
// 用户需要登录
if (localStorage.getItem('user')) {
next();
} else {
next({
path: '/login'
})
}
} else {
next();
}
})

题外:Vue相关开源项目库汇总