文章目录
1. Vue路由的相关概念
- 路由(routing)是指从源到目的地时,决定端到端路径的决策过程。
- 对于VueRouter而言,路由就是根据一个请求路径选中一个组件进行渲染的决策过程。
- Vue Router 是 Vue.js 官方的路由管理器。它和 Vue.js 的核心深度集成,让构建单页面应用变得易如反掌。
route
:
- 路由,可以理解为单个路由或者某一个路由。
- eg: Home按钮 ==> Home内容,这是一条路由
- eg:about按钮 ==> about内容,这是另一条路由
routes
:
- 多个路由的集合
- 官方定义routes是一个数组,所以routes表示多个路由(route)的集合。
router
:
- 路由器 可以理解为一个容器包含上述两个或者说它是一个管理者,负责管理上述两个。
- 举个常见的场景的例子:当用户在页面上点击按钮的时候,这个时候router就会去routes中去查找route,就是说路由器会去路由集合中找对应的路由;
VueRouter包括三个主要组成部分 —— VueRouter、router-view和 router-link
VueRouter
:路由器类,根据路由请求在路由视图中动态渲染选中的组件router-link
:路由链接组件,声明用以提交路由请求的用户接口router-view
:路由视图组件,负责动态渲染路由选中的组件
2. 安装vue-router
npm install vue-router
3. 开发一个VueRouter版的hello,world
3.1 创建路由器实例
- 路由器完全依赖于路由表来分发路由请求。
- 创建路由器实例时,需要使用
routes
配置项 来声明请求路径(path)和组件(component)的对应关系 ——
记录这一映射关系的对象,在VueRouter中被称为路由记(RouteRecord)。 - 路由器将根据routes路由记录数组来构造路由表。
eg: 创建了包含两条路由及记录的路由器实例router:
const myrouter = new VueRouter({
routes:[
{ path:'/', component: Home},
{ path:'/about', component: About}
]
})
// 当请求路径/时,路由器将选中组件Home
// 当请求路径/about时,路由器将选中组件About。
3.2 将路由器注入Vue实例
如果在一个Vue实例的模板中需要使用router-link和router-view组件,需要首先向这个Vue实例注入路由器对象,因为这两个组件都依赖于路由器对象:
在创建Vue实例时,使用router配置项将路由器对象注入Vue实例的$router
属性
const vm = new Vue({ router: myrouter })
console.log(vm.$router) //输出router
3.3 声明路由出口
路由视图组件(router-view)为路由器($router)提供了所选中组件的渲染出口。
在模板中,使用标签<router-view>
声明路由视图元素。
<router-view></router-view>
3.4 声明路由请求接口
路由链接组件(router-link)为用户提供了提交路由请求的交互接口。
使用to属性
来声明链接组件的目标路径。当用户点击链接组件时,组件向路由器提交向目标路径的路由请求。
在模板中,使用<router-link>
标签声明路由链接元素。
eg:声明了一个目标路径为/about的路由链接。
<router-link to="/about">ABOUT</router-link>
路由链接组件默认渲染为一个a元素,因此在视图DOM中,上面的模板对应于 DOM结构:
<a href="...">ABOUT</a>
4. Vue中路由跳转
4.1 标签导航router-link
标签导航<router-link>
,<router-link>
是通过转义为<a>
标签进行跳转,其中router-link标签中的to属性会被转义为a标签中的href属性
使用方式:
<router-link to='需要跳转到的页面的路径>文本</router-link>
浏览器在解析时,将它解析成一个类似于<a>
的标签。
不带参数使用:
<router-link :to="{name:'home'}">
<router-link :to="{path:'/home'}">
- name,path都行, 建议用name
- 注意: router-link中链接如果是’/‘开始就是从根路由开始,如果开始不带’/’,则从当前路由开始。
带参数使用:
<router-link :to="{name:'home', params: {id:1}}">
:
- params传参数 (类似post)
- 路由配置 path: “/home/:id” 或者 path: “/home:id”
- 不配置path ,第一次可请求,刷新页面id会消失
- 配置path,刷新页面id会保留
- html 取参:$route.params.id
- script 取参:this.$route.params.id
<router-link :to="{name:'home', query: {id:1}}">
:
- query传参数 (类似get,url后面会显示参数)
- 路由可不配置
- html 取参:$route.query.id
- script 取参:this.$route.query.id
4.2 编程式导航this.$router
路由器对象
this.$router表示全局路由器对象,项目中通过router路由参数注入路由之后,在任何一个页面都可以通过此属性获取到路由器对象,并调用其push()、go()等方法。
我们可以通过this.$router.push()这个方法来实现编程式导航,当然也可以实现参数传递,这种编程式导航一般是用于按钮点击之后跳转。
this.$router.push()
不带参数:
this.$router.push('/home')
this.$router.push({name:'home'})
this.$router.push({path:'/home'})
query传参(get请求):
this.$router.push({name:'home',query: {id:'1'}})
this.$router.push({path:'/home',query: {id:'1'}})
- html取参:$route.query.id
- script取参:this.$route.query.id
params传参:
this.$router.push({name:'home',params: {id:'1'}})
只能用 name
- 路由配置 path: “/home/:id” 或者 path: “/home:id”
- 不配置path ,第一次可请求,刷新页面id会消失
- 配置path,刷新页面id会保留
- html 取参:$route.params.id
- script 取参:this.$route.params.id
query和params区别:
- query类似 get, 跳转之后页面 url后面会拼接参数,类似?id=1, 非重要性的可以这样传, 密码之类还是用params刷新页面id还在
- params类似 post, 跳转之后页面 url后面不会拼接参数 , 但是刷新页面id 会消失
this.$router.replace()
this.$router.go(n)
this.$router.go(n)
:向前或者向后跳转n个页面,n可为正整数或负整数。
三个方法的小总结:
this.$router.push
:跳转到指定url路径,并向history栈中添加一个记录,点击后退会返回到上一个页面this.$router.replace
:跳转到指定url路径,但是history栈中不会有记录,点击返回会跳转到上上个页面
(就是直接替换了当前页面)this.$router.go(n)
:向前或者向后跳转n个页面,n可为正整数或负整数
eg:组件之间的参数传递
实现解析:
- 刚开始url路径默认匹配ResoureVue.vue组件
- 通过ResoureVue.vue组件的button按钮触发
$this.$router.push()
跳转到Select.vue组件并添加query请求参数id为45; - 在Select.vue组件中可通过
this.$route.query.id
获取到跳转的请求参数
具体实现:
- 创建ResoureVue.vue(请求组件):
<template>
<button @click="change">验证路由传参</button>
</template>
<script>
export default {
name: "ResoureVue",
data() {
return {
id: 45,
}
},
methods: {
change() {
this.$router.push({
path:'/select',
query: {
id: this.id
}
})
}
}
}
</script>
<style scoped>
</style>
- 创建Select.vue(接收请求组件):
<template>
<select>
<option value="1" selecte="selected">成都</option>
<option value="2">北京</option>
</select>
</template>
<script>
export default {
name: "Select",
data() {
return {
id:'',
}
},
created() {
this.id = this.$route.query.id;
console.log(this.id);
}
}
</script>
<style scoped>
</style>
- 新建文件夹router,在该文件夹中创建路由文件index.js:
import Vue from "vue";
import Router from "vue-router";
import ResoureVue from '@/components/001/ResoureVue'
import Select from '@/components/001/Select'
Vue.use(Router);
const router = new Router({
routes:[
{
path: '/res',
name: 'ResourceVue',
component: ResoureVue
},
{
path: '/select',
name: 'select',
component: Select
},
{
path: '/',
name: 'ResourceVue',
component: ResoureVue
},
{
path: '',
name: 'ResourceVue',
component: ResoureVue
}
],
mode: 'history'
})
export default router;
- 在main.js文件中配置自定义的路由文件:
import Vue from 'vue'
import App from './App.vue'
import router from '@/router'
new Vue({
router,
render: h => h(App),
}).$mount('#app')
- 在App.js文件配置导航:
<template>
<div id="app">
<router-link to="/res">路由发送请求组件</router-link>
<hr>
<router-link to="/select">路由接收请求组件</router-link>
<hr>
<router-view></router-view>
</div>
</template>
<script>
export default {
name: 'App',
}
</script>
<style>
</style>
eg:区别重定向和单独配置路由
- page1组件
<template>
<div>
<h1>page1</h1>
<p>{{ msg }}</p>
</div>
</template>
<script>
export default {
name: "page1",
data() {
return {
msg:'我是page1组件'
}
}
}
</script>
<style scoped>
</style>
- page2组件
<template>
<div>
<h1>page2</h1>
<p>{{ msg }}</p>
</div>
</template>
<script>
export default {
name: "page2",
data() {
return {
msg: '我是page2组件'
}
}
}
</script>
<style scoped>
</style>
- 路由文件router文件
import Vue from 'vue';
import VueRouter from 'vue-router';
import page1 from '@/components/002/page1'
import page2 from '@/components/002/page2'
Vue.use(VueRouter);
const router = new VueRouter({
routes:[
{
path:'/page1',
component: page1
},
{
path:'/page2',
component: page2
},
// 配置重定向
{
path:'',
redirect:'page1'
},
// 或者写一个路径为空的路由
// {
// path:'',
// component: page1,
// }
]
})
export default router;
- mian.js
import Vue from 'vue'
import App from './App.vue';
import router from '@/router/router'
new Vue({
router,
render: h => h(App),
}).$mount('#app')
- App.vue
<template>
<div id="app">
<router-link to="/page1">Page1</router-link>
<router-link to="/page2">Page2</router-link>
<router-view></router-view>
</div>
</template>
<script>
export default {
name: 'App',
}
</script>
<style>
</style>
5. 动态路由匹配
- 比如一个网站或者后台管理系统中,在我们登录之后,是不是通常会有一个欢迎回来,XXX之类的提示语,这个我们就可以通过动态路由来实现这个效果。
- 动态路由匹配给我们提供了方便,使得我们通过配置一个路由来实现页面局部修改的效果,给用户造成一种多个页面的感觉。
- 创建user.vue组件:
<template>
<div>
<h1>User</h1>
<!--这里可以通过$route.params.name来获取路由的参数-->
<p>欢迎回来,{{ $route.params.name }}</p>
</div>
</template>
<script>
export default {
name: "User",
}
</script>
<style scoped>
</style>
- router.js:
import Vue from 'vue';
import VueRouter from 'vue-router';
import User from '@/components/dongtai/User'
Vue.use(VueRouter);
const router = new VueRouter({
routes:[
{
path:'/user/:name',
component: User,
},
]
})
export default router;
- App.vue:
<template>
<div id="app">
<router-link to="/user/项羽">动态路由--项羽</router-link>
<hr>
<router-link to="/user/刘邦">动态路由--刘邦</router-link>
<router-view></router-view>
</div>
</template>
<script>
export default {
name: 'App',
}
</script>
<style>
</style>
6. 嵌套路由
- 比如当我们进入主页之后有分类,然后当选择其中一个分类之后进入对应的详情,这个时候我们就可以用到嵌套路由
- 官方文档中给我们提供了一个
children属性
,这个属性是一个数组类型,里面实际放着一组路由这个时候父子关系结构就出来了 - children属性里面的是路由相对来说是children属性外部路由的子路由。
import Vue from 'vue';
import VueRouter from 'vue-router';
import page1 from '@/components/002/page1'
import Phone from '@/components/qiantao/Phone'
import Computer from '@/components/qiantao/Computer'
import page2 from '@/components/002/page2'
Vue.use(VueRouter);
const router = new VueRouter({
routes:[
{
path:'/page1',
component: page1,
children: [
{
path: 'phone',
component:Phone,
},
{
path: 'computer',
component: Computer
}
]
},
{
path: '/page2',
component: page2
},
{
path:'',
component: page1,
}
]
})
export default router;
7. 路由的实现模式
Vue 中,它是通过 mode
这一参数控制路由的实现模式。
const router=new VueRouter({
mode:'history',
routes:[...]
})
mode参数:
- 默认 hash
- history 如果浏览器不支持 history 新特性,则采用 hash
- 如果不在浏览器环境下,就采用 abstract(Node环境下)
mode:"hash" 多了 “#” --- 默认的
http://localhost:8080/#/login
mode:"history"
http://localhost:8080/login