这是我参与8月更文挑战的第2天,活动详情查看: 8月更文挑战” 。
一、前言
在vue项目中,页面跳转已不再用 <a href="xxx"></a>这种方式,而是使用vue-router,所以接下来就看看vue-router在项目的应用。
二、Vue Router是什么
Vue Router 是 Vue.js官方的路由管理器。它和 Vue.js 的核心深度集成,让构建单页面应用变得易如反掌。
三、Vue Router的模式
Vue Router有两种模式:hash和history,在项目中通过mode设置模式,例如设置为history模式。
const router = new VueRouter({
mode: 'history',
routes: [...]
})
-
hash模式: vue-router默认hash模式——使用URL的hash来模拟一个完整的URL,于是当URL 改变时,页面不会重新加载。此模式生成的URL如http://localhost:8080/#/product/list 这种格式,会产生一个”#“符号,它是URL的锚点,后期改变路由只会改变#后面的部分,不会重新刷新当前页面。
vue-router默认hash模式——使用URL的hash来模拟一个完整的URL,于是当URL 改变时,页面不会重新加载。此模式生成的URL如这种格式,会产生一个”#“符号,它是URL的锚点,后期改变路由只会改变#后面的部分,不会重新刷新当前页面。 总结:Hash模式通过改变锚点值,渲染对应的rouer-view。
-
history模式: 看到hash模式下路径会有“#”,有些人可能会觉得这样很丑,如果不想要“#”,我们可以用路由的history模式,这种模式充分利用history.pushState API来完成URL跳转而无须重新加载页面。 当你使用history模式时,URL就像正常的url,例如http://localhost:8080/product/list。
不过这种模式上线时需要后台配置支持。因为我们的应用是个单页客户端应用,如果后台没有正确的配置,当用户在浏览器直接访问xxxx.com/product/lis… 就会返回404,这就不好了。
所以,需要在服务端增加一个覆盖所有情况的候选资源,如果URL匹配不到任何静态资源,则应该返回同一个index.html 页面,这个页面就是项目app依赖的页面。
四、Vue Router的使用
默认vue-cli创建项目时已经安装vue-router
- 在项目中src=>views文件夹下创建两个组件 Home.vue
<template>
<div>
<h1>Home</h1>
<div>{{message}}</div>
</div>
</template>
<script>
export default {
data () {
return {
message: "Home组件~"
}
}
}
</script>
About.vue
<template>
<div>
<h1>About</h1>
<div>{{About}}</div>
</div>
</template>
<script>
export default {
data () {
return {
message: 'About组件~'
}
}
}
</script>
- 在App.vue中留坑
<template>
<div id="app">
<!--router-link定义页面中点击触发部分 -->
<router-link to="/home">欢迎来到Home页面</router-link>
<router-link to="/about">欢迎来到About页面</router-link>
</div>
<!-- 留坑即对应的组件内容渲染到router-view中 -->
<router-view />
</div>
</template>
- 在src=>router文件夹下新建一个index.js,管理所有组件和路由的映射
import Vue from 'vue'
import VueRouter from 'vue-router'
Vue.use(VueRouter)
// 懒加载导入组件
const Home = () => import('@/views/Home')
const About = () => import('@/views/About')
const routes = [
{
path: '/home',
name: 'Home',
component: Home
},
{
path: '/about',
name: 'About',
component: About
}
]
const router = new VueRouter({
mode: 'hash',
base: process.env.BASE_URL,
routes
})
export default router;
这时点击页面上的Home和About可以看到组件来回切换。到此路由的基本使用就完成了。 但是有一个问题,当首次进入页面的时候,页面中并没有显示任何内容。这是因为首次进入页面时,它的路径是'/',我们并没有给这个路径做相应的配置。一般,页面一加载进来会显示首页。此时需要把这个路径指向Home组件,有两种方式可以解决这个问题。
-
重定向
所谓重定向,就是重新给它指定一个方向,它本来是访问 / 路径,我们重新指向“/home”, 它就相当于访问 “/home”, 相应地, Home组件就会显示到页面上。Vue Router中用redirect来定义重定向。
-
设置一个路径为空的路由
重新配置个路由,路径为空的时候router-view展示home的页面
const routes = [
{
path:"/home",
component: Home
},
{
path: "/about,
component: About
},
// 重定向
{
path: '/',
redirect: '/home'
}
// 或者重新写个路径为空的路由
{
path: '',
redirect: '/home'
}
]
到此,页面可以正常访问了,首次进入显示Home, 并且点击也可以看到内容的切换。
用重定向和重新配置路由的区别:
- 重定向实际上是当匹配到路径符合条件的时候去执行对应的路由,当然这个时候的url上面的地址显示的是对应的路由,页面也是对应的路由页面;
- 重新配置路由是当匹配到路径符合条件的时候,router-view页面展示部分找到符合条件路由的页面来展示,实际上url是没有发生变化的;
动态路由匹配:
在项目中有这样的一种需求,比如详情页面,通常是根据ID展示对应的内容,这个我们就可以通过动态路由来实现这个效果。 首先在src目录下新建一个Detail.vue文件:
<template>
<div>
<h1>详情</h1>
//这里可以通过$route.params.id
<p>{{$route.params.id}}</p>
</div>
</template>
<script>
export default {
data () {
return {
msg: "我是Detail组件"
}
}
}
</script>
然后我们修改App.vue文件的代码:
<template>
<div id="app">
<div>
<router-link to="/home">欢迎来到Home页面</router-link>
<router-link to="/about">欢迎来到About页面</router-link>
</div>
//添加两个router-link标签
<div>
<router-link to="/detail/1">详情一</router-link>
<router-link to="/detail/2">详情二</router-link>
</div>
<router-view></router-view>
</div>
</template>
<script>
export default {
name: 'App'
}
</script>
修改我们的router.js
import Vue from 'vue';
import VueRouter from 'vue-router';
Vue.use(VueRouter)
const Home = () => import('@/views/Home')
const About = () => import('@/views/About')
const Detail = () => import('@/views/Detail')
const routes=[
{
path:"/home",
component: Home
},
{
path: "/about,
component: About
},
//使用冒号标记,当匹配到的时候,可以通过this.$route.params获取参数值
{
path: "/detail:id,
component: Detail
},
// 重定向
{
path: '/',
redirect: '/home'
}
]
const router=new VueRouter({
routes
});
export default router
动态路由匹配给我们提供了方便,使得我们通过配置一个路由来实现页面局部修改的效果。 由于使用路由参数,从/detail/1到/detail/2,两个路由都渲染同一个组件,原来的组件实例会被复用,比起销毁再创建,显示复用显得效率更高,带来的的问题就是生命周期钩子函数不会再被调用,也就是不会再被触发;如果想在路由改变时做些什么操作,我们可以通过监听$route来实现;
修改Detail.vue的代码
<template>
<div>
<h1>详情</h1>
//这里可以通过$route.params.name来获取路由的参数
<p>{{$route.params.name}}</p>
</div>
</template>
<script>
export default {
data () {
return {
msg: "我是Detail组件"
}
},
watch:{
//to表示即将要进入的那个组件,from表示从哪个组件过来的
$route(to,from){
this.msg=to.params.id;
console.log(111);
<!--TODO-->
}
}
}
</script>
嵌套路由:
在项目中,有些业务流程的页面结构决定了可能会需要使用嵌套路由,比如下面这种情况:
点击上面的步骤条然后展示相对应的内容,这个时候我们就可以用到嵌套路由;官方文档中给我们提供了一个children属性,children 配置就是像routes 配置一样的路由配置数组。
首先在我们的src目录下新建两个vue文件,分别是EditBasicInfo.vue和EditParams.vue
EditBasicInfo.vue
<template>
<div>
<p>{{msg}}</p>
</div>
</template>
<script>
export default {
data () {
return {
msg: "编辑基本信息"
}
}
}
</script>
computer.vue
<template>
<div>
<p>{{msg}}</p>
</div>
</template>
<script>
export default {
data () {
return {
msg: "编辑产品参数"
}
}
}
</script>
然后我们再修改我们的App.vue文件:
<template>
<div id="app">
<div>
<router-link to="/home">Home</router-link>
</div>
<router-view></router-view>
</div>
</template>
<script>
export default {
name: 'App'
}
</script>
我们再来修改router.js
import Vue from 'vue';
import VueRouter from 'vue-router';
Vue.use(VueRouter)
const Home = () => import('@/views/Home')
const About = () => import('@/views/About')
const Detail = () => import('@/views/Detail')
const EditBasicInfo = () => import('@/views/EditBasicInfo')
const EditParams = () => import('@/views/EditParams')
const routes=[
{
path:"/home",
component: Home,
children: [
{
path: "edit-basc-info",
component: EditBasicInfo
},
{
path: "edit-params",
component: EditParams
},
]
},
{
path: "/about,
component: About
},
//使用冒号标记,当匹配到的时候,参数值会被设置到this.$route.params中
{
path: "/detail:id,
component: Detail
},
// 重定向
{
path: '/',
redirect: '/home'
}
]
const router=new VueRouter({
routes
});
export default router
children属性其实就是一个子路由集合,数组结构里面放着子路由。
路由导航两种方式:
声明式导航:<router-link><router-link>转义为<a></a>标签进行跳转,其中router-link标签中的to属性会被转义为a标签中的href属性;
例如:跳转到名为detail路由,并传递参数id
<router-link :to="{ name: 'Detail', params: { id: 1 }}">详情内容</router-link>
编程式导航:通过this.$router.push()这个方法来实现编程式导航,并且也可以传递参数,在项目中的常用场景有点击某个按钮或者向服务端提交数据请求成功之后跳转页面。
router.push({ path: `/detail/${id}`})
// 这里的 params 不生效
// router.push({ path: '/detail', params: { id:1 }}) // -> /detail
这两种方式都会跳转到detail/1这个路径。
命名路由:
有时候,通过一个名称来标识一个路由显得更方便一些,特别是在链接一个路由,或者是执行一些跳转的时候。你可以在创建 Router 实例的时候,在 routes 配置中给某个路由设置名称。
- 普通路由:
router.push({ path: '/detail/:id', params: { id: 1 }})
- 命名路由:
router.push({ name: 'Detail', params: { id: 1 }})
这两种方式都会把路由导航到 /detail/1路径。