跳到主要内容

3.1-vue-router

Create by fall on 11 Apr 2021 Recently revised in 01 Sep 2022

路由

路由的本质就是 URL 的对应关系,分为前端路由后端路由

后端路由

PHP 这类的动态资源网页。根据用户不同的 URL 请求 ,返回不同的内容,服务器动态生成的页面。

如果用户经常提交表单,会造成网页的频繁刷新,因此出现了 ajax 技术,实现局部刷新。ajax 技术不支持浏览器的前进后退。即浏览器无法保存用户在网页的浏览状态,因此出现了 SPA 单页面开发技术。

后端路由的本质:URL 地址和服务器资源之间的关系

前端路由

根据不同的用户事件,显示不同的内容(页面路由被前端 JS 监听并控制)。

每当用户触发一个事件后,会被路由监听到,路由会把这次请求分发给对应的事件处理函数,紧接着事件处理函数会渲染对应的内容,呈现给用户。(前端路由负责事件监听,触发事件后,通过事件函数渲染不同的内容

SPA:单页面应用程序,整个网站只有一个页面,内容通过 ajax 局部刷新实现,同时支持浏览器的前进后退功能。

Vue-Router

vue-router 是 vue 实现,控制路由的官方插件

在组合式 API 中,想要调用路由,有两个方法

  • useRouter 使用全局路由对象,对应 $router
  • useRoute 获取当前路由下的信息,对应 $route

下面来详细说说两者的不同:

useRouter 表示的是全局路由对象,用来控制当前页面的路由

import {useRouter} from 'vue-router'
// useRouter 返回全局路由对象
const router = useRouter()
// router 等价于选项式 API 中的 $router
// push 用来跳转到对应路由
router.push('login')
router.push({path:'home'})
router.push({name:'user',params:{id:12314}})
router.push({ path: 'register', query: { plan: '123' }})
// replace 用来替换当前路由,push 会留下历史,replace 不会
router.replace({path:'home'})
// go 通常指前进后退
router.go(-1) // 回退

useRoute 返回当前路由对象

import {useRoute} from 'vue-router'
// useRouter 返回全局路由对象
// route 等价于选项式 API 中的 $route
const route = useRoute()

route.path
// 字符串,对应当前路由的路径,总是解析为绝对路径,如 "/foo/bar"。
route.params
// 一个 key/value 对象,包含了动态片段 和 全匹配片段,如果没有传入,就是一个空对象。
route.query
// 一个 key/value 对象,表示 URL 查询参数。
// 例如,对于路径 /foo?user=1,则有 $route.query.user == 1,
// 如果没有查询参数,则是个空对象。
route.hash // 当前路由的 hash 值 (不带 #) ,如果没有 hash 值,则为空字符串。锚点
route.fullPath // 完成解析后的 URL,包含查询参数和 hash 的完整路径。
route.matched // 数组,包含当前匹配的路径中所包含的所有片段所对应的配置参数对象。
route.name // 当前路径名字
route.meta // 路由元信息

路由守卫

全局守卫

  • router.beforeEach 全局前置守卫 进入路由之前
  • router.beforeResolve 全局解析守卫(2.5.0+) 在 beforeRouteEnter 调用之后调用
  • router.afterEach 全局后置钩子 进入路由之后
// main.js 入口文件
import router from './router'; // 引入路由
router.beforeEach((to, from, next) => {
next();
});
router.beforeResolve((to, from, next) => {
next();
});
router.afterEach((to, from) => {
console.log('afterEach 全局后置钩子');
});

参数:

  • to:表明前往的路由
  • from:表明从哪里来
  • next:表示进行接下来的内容,必须要进行调用,调用方式如下
    • next():进入下一个路由
    • next(false):取消进入下一个路由
    • next('path'):进入 path 路由,或者和 router.push 相同的参数

独享守卫

const routers = [
{
path:'/path',
component:()=>import('./Page.vue')
beforeEnter: (to, from, next) => {
// 参数用法什么的都一样,调用顺序在全局前置守卫后面,所以不会被全局守卫覆盖
// ...
}
}
]
  • beforeRouteEnter 进入路由前
  • beforeRouteUpdate (2.2) 路由复用同一个组件时
  • beforeRouteLeave 离开当前路由时
const route = {
beforeRouteEnter (to, from, next) {
// 在路由独享守卫后调用 不!能!获取组件实例 `this`,组件实例还没被创建
},
beforeRouteUpdate (to, from, next) {
// 在当前路由改变,但是该组件被复用时调用 可以访问组件实例 `this`
// 举例来说,对于一个带有动态参数的路径 /foo/:id,在 /foo/1 和 /foo/2 之间跳转的时候,
// 由于会渲染同样的 Foo 组件,因此组件实例会被复用。而这个钩子就会在这个情况下被调用。
},
beforeRouteLeave (to, from, next) {
// 导航离开该组件的对应路由时调用,可以访问组件实例 `this`
}
}

路由错误捕获

router.onError(err=>{
console.log(err)
})

Vue路由

官网:https://next.router.vuejs.org/zh/introduction.html

包含功能:

支持HTML5历史模式和hash模式,支持嵌套路由,支持路由参数,支持编程式路由,支持命名式路由。

注:该文档是使用 Vue2 做的示例,所以,如果是 Vue3 的项目,尽量不要参考该代码。

路由的使用

这里的使用都是 .html 界面中路由的使用,不是 .vue 文件中路由的使用

<!-- 在引入vue.js 之后引入 vue-router.js -->
<div class='app'>
<router-link to="/home">Register</router-link>
<router-link to="/user">User</router-link>
<router-view></router-view>
<!-- 作为路由占位符 -->
</div>
<script>
const Home = {
template:`<h1>主页</h1>`
}
const User = {
template:`<h1>用户页面</h1>`
}
const router = new VueRouter({
routes:[
{path:'/home',component:Home},
{path:'/user',component:User}
]
})
const app = new Vue({
el:".app",
router:router,// 挂在实例对象
data:{}
})
</script>

嵌套路由

<div class='app'>
<router-link to="/home">Register</router-link>
<router-link to="/user">User</router-link>
<router-view></router-view>
<!-- 作为路由占位符 -->
</div>
<script>
const goudan = {
template:`<h2>狗蛋</h2>`
}
const mahua ={
template:`<h2>麻花</h2>`
}
const User = {
template:`
<div>
<h1>用户</h1>
<router-link to="/user/goudan">李狗蛋</router-link>
<router-link to="/user/mahua">李麻花</router-link>
<router-view></router-view>
</div>
`,
component:{}
}
const router = new VueRouter({
routes:[
{path:'/',redirect:'/home'},
{path:'/home',component:Home},
{path:'/user',component:User,children:[{
path:'/user/mahua',component:mahua
},{
path:'/user/goudan',component:goudan
}]}
]
})
const app = new Vue({
el:".app",
router:router,// 挂在实例对象
data:{
},
})
</script>

动态路由

动态路由是为了满足多个相似路径的路由的需要

<div class='app'>
<router-link to="/home">Register</router-link>
<router-link to="/user/12">User12</router-link>
<router-link to="/user/33">User33</router-link>
<router-link to="/user/62">User62</router-link>
<router-view></router-view>
</div>
<script>
const Home = {
template: `<h1>主页</h1>`
}
const theUser = {
template: `<h1>{{$route.params.name}}</h1>`
}
// theUser2 是利用动态路由匹配,props = true 后可以直接将 theUser 换成 theUser2,
const theUser2
const router = new VueRouter({
routes: [
{ path: '/', redirect: '/home' },
{ path: '/home', component: Home },
{ path: '/user/:name', component: theUser ,props:true}
]
})
const app = new Vue({
el: ".app",
router: router,// 挂在实例对象
data: {},
})
</script>

命名路由

<router-view :to='{name:user,parames:{id:999}}'></router-view>
<!--需要为router内的函数设置一个值 -->

导航方式

声明式导航

利用<a href="#5566">链接</a> ,和<router-link></router-link>

编程式导航

调用JavaScript API来实现导航的方式,成为编程式导航

location.herf()

vue中的导航基本用法

this.$router.push('hash地址')
this.$router.go(n) // 填数字,可以前进或者后退n位
this.$router.push({path:'/home'})
this.$router.push({name:'/home',parames})

强制重定向

访问a地址的时候,强制用户跳转到地址c,从而展示特定的组件页面

route和router

通过 params 传值时,必须使用 name,而不是 path

route

表示当前路由中解析的信息,还有匹配到的 route records(路由记录)

路由信息功能
$route.path字符串,对应当前路由的路径,总是解析为绝对路径,如 "/foo/bar"。
$route.params一个对象,包含了 动态片段 和 全匹配片段,
如果没有路由参数,就是一个空对象。
$route.query一个对象,表示 URL的查询字符串。
例如,对于路径 /foo?user=1,则有 $route.query.user == 1
如果没有查询参数,则是个空对象。
$route.hash当前路由的 hash 值 (不带 #) ,如果没有 hash 值,则为空字符串。
$route.fullPath完成解析后的 URL,包含查询参数和 hash 的完整路径。
$route.matched数组,包含当前匹配的路径中所包含的所有片段所对应的配置参数对象。
$route.name路径的名称
$route.meta路由元信息

router

全局的路由实例,是router构造方法的实例。

内部的实例

const router = new Router({
routes: [
{
path: "/",
name: "首页",
redirect: '/home'
},
{
path: '/login',
name: 'Login',
component: Login
},
{ path: '*', component: NotFoundComponent }
],
linkActiveClass: "active-router",
linkExactActiveClass: "exact-router"
})

路由的实例方法

// push方法其实和<router-link :to="...">是等同的。
// 字符串
this.$router.push('home')
// 对象
this.$router.push({ path: 'home' })
// 命名的路由
this.$router.push({ name: 'user', params: { userId: 123 }})
// 带查询参数,变成 /register?plan=123
this.$router.push({ path: 'register', query: { plan: '123' }})

路由守卫

路由守卫作用在router上

// 全局前置守卫
router.beforeEach(to,from,next){
console.log('to表示要前往的界面');
console.log(to);
console.log('from 表示从哪个页面过来');
console.log(from);
console.log('------------next----------');
console.log(next);
next(false)
// next(false) 中断当前的导航。
}

文章参考

作者连接
Ishmael丶Yokohttps://www.jianshu.com/p/fa0b5d919615
OBKoro1https://juejin.cn/post/6844903641866829838