主要就结合我做的一个商户后台的应用来学习一下路由
这个应用主要有
- 登录页
/login
- 注册页
/register
- 404页面
404
- 首页
/home
- 以及在首页里面通过路由来跳转的各个页面
/home/xxx
- 以及在首页里面通过路由来跳转的各个页面
我们使用vue脚手架快速原型开发, 使用的是 @vue/cli 3.x 版本的
1. 安装
npm install -g @vue/cli
# OR
yarn global add @vue/cli
2. 创建项目
vue create hello-world
看到src/ 下的 main.js
// main.js 来渲染 App 作为顶层出口
import Vue from 'vue'
import App from './App.vue'
new Vue({
router,
render: h => h(App)
}).$mount('#app')
我们把 App 作为顶层, 来渲染登录, 注册, 首页等同一级的组件
// App.vue
<template>
<div id="app">
<router-view/> // <router-view> 是最顶层的出口,渲染最高级路由匹配到的组件.
</div>
</template>
每个路由映射一个组件
// router.js
import Vue from 'vue'
import Router from 'vue-router'
import Home from './views/Home.vue'
Vue.use(Router)
const router = new Router({
routes: [
{
path: '/login', // path : 路径
name: 'Login', // 给某个路由设置名称。
component: () => import('./views/login.vue') // 动态加载对应路由
},
{
path: '/register',
name: 'Register',
component: () => import('./views/register.vue')
},
{
path: '/',
name: 'home',
redirect: '/home/index', // 重定向, 从 / 重定向到 /home/index
component: Home,
meta: { // 路由元信息
requiresAuth: true
},
}
]
})
export default router
这样我们就可以在浏览器url
中输入不同的 path
值, 链接到对应的 vue
组件
带 # 号是因为 url 是 hash 模式
http://localhost:8080/#/login // 对应登录组件
http://localhost:8080/#/register // 对应注册组件
http://localhost:8080/#/home/index // 对应首页
我们来看一下 home
组件的组成
<template>
<div id="home">
<y-header></y-header> // 使用组件
<Row class="center_view">
<Col span="4">
<y-side></y-side>
</Col>
<Col span="20">
<router-view/> // 又是一个 router-view, 可以渲染home 下 不同 url 的组件, 嵌套路由
</Col>
</Row>
</div>
</template>
<script>
import YHeader from './../components/YHeader' // 引入组件
import YSide from './../components/YSide'
export default {
name: 'home',
components: {
YHeader,YSide // 注册组件到这个页面
}
}
</script>
要在嵌套的出口中渲染组件,需要在 Router
路由的参数中使用 children
配置
// router.js
import Vue from 'vue'
import Router from 'vue-router'
import Home from './views/Home.vue'
Vue.use(Router)
const router = new Router({
routes: [
{
path: '/login', // path : 路径
name: 'Login', // 给某个路由设置名称。
component: () => import('./views/login.vue') // 动态加载对应路由
},
{
path: '/register',
name: 'Register',
component: () => import('./views/register.vue')
},
{
path: '/',
name: 'home',
redirect: '/home/index', // 重定向, 从 / 重定向到 /home/index
component: Home,
meta: { // 路由元信息
requiresAuth: true
},
// children 配置就是像 routes 配置一样的路由配置数组,所以呢,你可以嵌套多层路由。
children: [ // 配置嵌套路由的 Children
{
path: '/home/a', // router-view 可以渲染 A
name: 'A',
component: () => import('./views/shopManagement/A.vue')
},
{
path: '/home/b', // // router-view 可以渲染 B
name: 'B',
component: () => import('./views/shopManagement/B.vue')
},
]
}
]
})
export default router
对于后台, 我们可以设置侧边栏有不同的分级, 点击不同的跳转到对应的
<!-- 使用 router-link 组件来导航. -->
<!-- 通过传入 `to` 属性指定链接. -->
<!-- <router-link> 默认会被渲染成一个 `<a>` 标签 -->
<router-link to="/home/a">
<span>跳转到a链接</span>
</router-link>
<router-link to="/home/b">
<span>跳转到b链接</span>
</router-link>
我们也可以使用编程式导航
想要导航到不同的 URL,则使用 router.push 方法
上面的 router-link 等同于
this.$router.push({path: '/a'})
this.$router.push({name: 'A'})
如果我们需要把 a 组件里值传给 b 组件, 我们可以使用路由传参
- 可以使用
query
传参 - 可以使用
params
传参
// query 方式传参和接受参数
query相当于get请求,页面跳转的时候,可以在地址栏看到请求参数
传参
this.$router.push({
path: '/xxx',
query: {
id: id
}
})
接受参数
this.$route.query.id
** 注意:传参是this.$router,接收参数是this.$route
url 是这样的: /xxx?id=123
// params 方式传参和接受参数
传参
this.$router.push({
name: 'xxx', // 命名路由的名字
params: {
id: id
}
})
接收参数
this.$route.params.id
url 是这样的 /xxx/123
- 两者的区别
路由设置这里,当你使用 params 方法传参的时候,要在路由后面加参数名,并且传参的时候,参数名要跟路由后面设置的参数名对应
{
path: '/home/a/:id', // 接收参数的路由, 使用 params传参要加参数名, id 就是参数名
name: 'A',
component: () => import('./views/shopManagement/A.vue')
},
使用query方法,就没有这种限制,直接在跳转里面用就可以
** 注意:如果路由上面不写参数,也是可以传过去的,但不会在url上面显示出你的参数,并且当
你跳到别的页面或者刷新页面的时候参数会丢失(如下图所示),那依赖这个参数的http请求
或者其他操作就会失败。
1、params是路由的一部分,必须要有。query是拼接在url后面的参数,没有也没关系。
params一旦设置在路由,params就是路由的一部分,如果这个路由有params传参,但是在
跳转的时候没有传这个参数,会导致跳转失败或者页面会没有内容。
上面路由基本就是Vue 的大部分功能可以使用了
路由高级一点的也有一些导航守卫可以使用
- 全局的
router.beforeEach 注册一个全局前置守卫
const router = new VueRouter({
// ...
})
router.beforeEach((to, from, next) => {
})
// to: Route: 即将要进入的目标路由对象
// from: Route: 当前导航正要离开的路由
// 确保要调用 `next` 方法,否则钩子就不会被 resolved。
router.afterEach 注册一个全局后置钩子
router.afterEach((to, from) => {
// ...
})
- 路由独享的
const router = new VueRouter({
routes: [
{
path: '/foo',
component: Foo,
beforeEnter: (to, from, next) => {
// ...
}
}
]
})
- 组件内的守卫
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`
}
}
beforeRouteEnter 守卫 不能 访问 this,因为守卫在导航确认前被调用,因此即将登场的新组件还没被创建。
不过,你可以通过传一个回调给 next来访问组件实例。在导航被确认的时候执行回调,并且把组件实例作为回调方法的参数。
beforeRouteEnter (to, from, next) {
next(vm => {
// 通过 `vm` 访问组件实例
})
}
完整的导航解析流程
- 导航被触发。
- 在失活的组件里调用离开守卫。
- 调用全局的 beforeEach 守卫。
- 在重用的组件里调用 beforeRouteUpdate 守卫 (2.2+)。
- 在路由配置里调用 beforeEnter。
- 解析异步路由组件。
- 在被激活的组件里调用 beforeRouteEnter。
- 调用全局的 beforeResolve 守卫 (2.5+)。
- 导航被确认。
- 调用全局的 afterEach 钩子。
- 触发 DOM 更新。
- 用创建好的实例调用 beforeRouteEnter 守卫中传给 next 的回调函数。
网友评论