路由出现的背景
在vue中切换页面,实际上是切换组件,我们面临下面的问题:
http://localhost:8080/#/movies
如何根据路径中的地址选择不同的组件?
把选择的组件放在哪个位置?
怎样无刷新的切换组件?
路由插件
安装路由插件
npm i vue-router
使用路由插件,在main.js中
import Vue from 'vue'
import VueRouter from 'vue-router'
Vue.use(VueRouter); // Vue.use(插件) 在Vue中安装插件
const router = new VueRouter({
// 路由配置
})
new Vue({
...,
router
})
路由的基本使用
vue-router 匹配到的组件会渲染到<router-view>组件所在的位置。
// 路由配置
const router = new VueRouter({
routes: [ // 路由规则
// 当匹配到路径 /foo 时,渲染 Foo 组件
{ path: '/foo', component: Foo },
// 当匹配到路径 /bar 时,渲染 Bar 组件
{ path: '/bar', component: Bar }
]
})
<!-- App.vue -->
<div class="container">
<div>
<!-- 其他区域 -->
</div>
<div>
<!-- 页面区域 -->
<!-- vue-router 匹配到的组件会渲染到这里 使用<router-view>标签也可以-->
<!-- 这个组件实际上是vue内部的一个组件-->
<RouterView />
</div>
</div>
路由模式
路由模式决定了:
1、路由从哪里获取访问路径
2、路由如何改变访问路径
vue-router提供了三种路由模式,以下是常见的两种
1、hash:默认值。路由从浏览器地址栏中的hash部分获取路径,改变路径也是改变的hash部分,改变hash不会导致页面刷新。但是在实际应用中我们需要改变除了hash之外的路径,因此需要使用下面的history模式。
http://localhost:8080/#/movies --> /movies
http://localhost:8080/about#/movies --> /movies
2、history:路由从浏览器地址栏的location.pathname中获取路径,改变路径使用的H5的history api。需要浏览器支持history api
http://localhost:8080/#/movies --> /
http://localhost:8080/about#/movies --> /about
http://localhost:8080/movies --> /movies
修改路由模式的方法
const router = new VueRouter({
// 路由配置
routes,//路由匹配规则
mode: "history"
})
导航
当我们确定使用了history模式,使用传统的a元素,会刷新页面,随之带来的是请求html、js、css、执行js、创建vue应用、渲染全部组件树、挂载到指定的div中。如何做到不刷新,就不能使用传统的a元素,使用导航,就可以使用它来进行跳转。
vue-router
提供了全局的组件RouterLink
,它的渲染结果是一个a
元素
<RouterLink to="/blog">文章</RouterLink>
<!-- mode:hash 生成 -->
<a href="#/blog">文章</a>
<!-- mode:history 生成 -->
<!-- 为了避免刷新页面,vue-router实际上为它添加了点击事件,并阻止了默认行为,在事件内部使用hitory api更改路径 -->
<a href="/blog">文章</a>
路由匹配过程
1、首次请求,如:http://localhost:8080/,进行页面刷新,执行js,创建vue应用,进行渲染,当渲染到<RouterView />这个占位区域的时候,就会进行匹配,根据路由模式,得到路径,如history模式就会得到/,根据路由规则进行匹配,就会匹配到首页,就把首页渲染到<RouterView />这个占位区域。
2、当点击某个按钮需要切换页面时,通过<RouterLink
>组件进行导航,根据路由模式,得到路径,浏览器的地址栏会发生变化,路由插件会获取访问路径,到路由规则中匹配,匹配到的组件会渲染到<router-view>所在的位置。
激活状态
它解决的问题就是选中的效果。
默认情况下,vue-router
会用 当前路径 匹配 导航路径 :
- 如果当前路径是以导航路径开头,则算作匹配,会为导航的a元素添加类名
router-link-active
- 如果当前路径完全等于导航路径,则算作精确匹配,会为导航的a元素添加类名
router-link-exact-active
例如,当前访问的路径是/blog
,则:
导航路径 | 类名 |
---|---|
/ | router-link-active |
/blog | router-link-active router-link-exact-active (一个是匹配的/后的样式,一个是精确匹配到blog的样式) |
/about | 无 |
/message | 无 |
可以为组件RouterLink
添加bool属性exact
,将匹配规则改为:必须要精确匹配才能添加匹配类名router-link-active。在各个
组件RouterLink,通过配置
exact的值不同,来控制不同的效果。
例如,当前访问的路径是/blog
,则:
导航路径 | exact | 类名 |
---|---|---|
/ | true | 无 |
/blog | false | router-link-active router-link-exact-active |
/about | true | 无 |
/message | true | 无 |
例如,当前访问的路径是/blog/detail/123
,则:
导航路径 | exact | 类名 |
---|---|---|
/ | true | 无 |
/blog | false | router-link-active |
/about | true | 无 |
/message | true | 无 |
另外,可以通过active-class
属性更改匹配的类名,通过exact-active-class
更改精确匹配的类名
命名路由
使用命名路由可以解除系统与路径之间的耦合
// 路由配置
const router = new VueRouter({
routes: [ // 路由规则
// 当匹配到路径 /foo 时,渲染 Foo 组件
{ name:"foo", path: '/foo', component: Foo },
// 当匹配到路径 /bar 时,渲染 Bar 组件
{ name:"bar", path: '/bar', component: Bar }
]
})
<!-- 向to属性传递路由信息对象 RouterLink会根据你传递的信息以及路由配置生成对应的路径 -->
<RouterLink :to="{ name:'foo' }">go to foo</RouterLink>