(syntax)vue-router
2022-09-01 00:00:00

vue-router

  • 动态路由匹配 /:id/:name 路由参数、查询、通配符
  • 嵌套路由 children:[]
  • 编程式的导航 router.replace/push/replace/go
  • 命名路由router-link name
  • 命名视图 router-view name
  • 重定向和别名redirect alias
  • 路由组件传参 { name:"",params:{} }
  • 导航守卫 3全局beforeEach/Resolve/afterEach+ 1路由beforeEnter+ 3组件beforeRouter + Enter、Update、Leave
  • 路由元信息 meta
  • 不同的历史模式
1
2
npm install vue-router@4
yarn add vue-router@4
  • vue官方的路由管理器 组件树/路由树
  • 所有的路由抽离出来方便管理(集中管理) 路由传递参数 、动态传递参数

后端路由 vs 前端路由

  • 前端路由: 对于单页面应用程序来说,主要通过 URL 中的 hash(#号)来实现不同页面之间的切换,同时,hash 有一个特点:HTTP 请求中不会包含 hash 相关的内容;所以,单页面程序中的页面跳转主要用 hash 实现。(前端当前页面的跳转)
  • 后端路由: URL 对应服务器上的资源

命名路由和视图

  • router-link to replace append tag active-class 相当于 a链接 to 相当于 href 命名路由
  • router-view name 显示匹配的组件 占位符 视图占位符
  • v-slot 作用域插槽暴露第底层的定制能力,主要面向库作者、但也可以为开发者提供便利

编程式的导航(操作浏览器的历史记录和跳转记录)

  • router-link router.push router.replace router.go(n)
    • 当你点击 <router-link> 时,这个方法会在内部调用router.push(…),所以说,点击 <router-link :to="..."> 等同于调用 router.push(...)
    • router.replace(没有记录 回不去) 跟 router.push 很像,唯一的不同就是,它不会向 history 添加新记录,而是跟它的方法名一样 —— 替换掉当前的 history 记录
    • router.go(n)参数是一个整数,意思是在 history 记录中向前或者后退多少步,类似 window.history.go(n)
声明式 html编程式 js
<router-link :to="...">router.push(...)
<router-link :to="..." replace>·router.replace(...)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
// 字符串
$router.push('home')
// 对象
router.push({ path: 'home' })
// 命名的路由
router.push({ name: 'user', params: { userId: '123' }})
// 带查询参数,变成 /register?plan=private
router.push({ path: 'register', query: { plan: 'private' }})
const userId = '123'
router.push({ name: 'user', params: { userId }}) // -> /user/123
router.push({ path: `/user/${userId}` }) // -> /user/123
// 这里的 params 不生效
router.push({ path: '/user', params: { userId }}) // -> /user

router.go(1) // -1 3 10

router 构建选项 实例属性 实例方法

  • path 跳转的路径
  • name 命名路由 指定该路径名称
  • redirect 重定向
  • component 组件
  • children 路由嵌套
  • alias 别名path:'/a'(实际访问),componet: A,alias:'/b'(url展示出来假的)
  • mode hash模式
  • meta 路由元信息

route

  • $route对象,一个路由匹配到的所有路由记录会暴露为 this.$route 对象 路由对象
  • this.$router router 实例 (全局)
  • this.$route 当前激活的路由信息对象 (局部)
    • 传递参数 $route.query ? query
    • this.$route.params 使用params 方式传递路径 来获取路由中的参数
    • $route.hash
router-link是一个a链接 to(router.push() 目标路由的链接 )、replaceappendtagactive-class
router-viewname 设置了名称,则会渲染对应的路由配置中
v-slot作用域插槽暴露第底层的定制能力,主要面向库作者、但也可以为开发者提供便利
Router构建选项routes、mode、base、linkActiveClass 、linkExactActiveClass 、scrollBehavior 、parseQuery 、stringifyQuery、fallback
Router实例属性app、mode、currentRoute、START_LOCATION
Router实例方法()berforeEach、beforeResolve、afterEach、push、replace、go、back、forward、getMatchedComponent、resolve、addRoutes、addRoute、addRoutes、onReady、onError
路由对象$route.path 、``$route.params$route.query $route.hash$route.fullPath`、**$route.matched$route.name$route.redirectedFrom**
组件注入注入的属性 this.$router router 实例
this.$route 当前激活的路由信息对象、属性只读、属性不可变、可以watch它
增加的组件配置选项
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
npm i vue-router
vue add vue-router
// 导入 Vue.use()注册
// router/index.js 文件夹
import Vue from 'vue'
import VueRouter from 'vue-router'
import HomeView from '../views/HomeView.vue'
Vue.use(VueRouter)

const routes = [ // routes 数组
{
path: '/', //
redirect:'/home' // 重定向
alias:"/home";//别名,即访问“/”和“/home”跳转到同一个页面 展示出来的 假的
mode:'history';//默认为hash模式,在url上会加个#,比较难看,一般采用‘history’
meta: { requiresAuth: true } //路由元信息
},
{
path: '/homeview',
name: 'homeview',
component: HomeView,
children:[
{ path:"homeviewson1",component:() => import('./views/homeviewson1.vue')//懒加载的方式 },
{ path:"homeviewson2",component:homeviewson2 }
]
},
{
path: '/about',
name: 'about',
component: function () {
return import(/* webpackChunkName: "about" */ '../views/AboutView.vue')
}
}
]

const router = new VueRouter({
mode: 'history',
base: process.env.BASE_URL,
routes,
linkActiveClass :'myactive' // 路由高亮 myactive类名
})

// .router-link-active{ }

export default router

// vue3 routes = [] 中间不变
import { createRouter, createWebHashHistory } from 'vue-router'
import HomeView from '../views/HomeView.vue'

const router = createRouter({
history: createWebHashHistory(),
routes
})

export default router
  • created() { this.$route.query this.$route.params 获取路由参数
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
// vue
// main.js 导入 使用
import Vue from 'vue'
import router from './router' // 导入
import store from './store' //

new Vue({
router, // 使用
store,
render: function (h) { return h(App) } // render:h => h(APP)
}).$mount('#app')

// vue3
import { createApp } from 'vue'
import App from './App.vue'
import router from './router'
import store from './store'
createApp(App).use(store).use(router).mount('#app')

// App.vue
<router-link to="/">Home</router-link> // 默认渲染a标签 自定义标签
<router-link to="/login?id=1000&name=zs">Home</router-link> // 传递参数
// 绑定动态传递参数
<router-link :to="home">Home</router-link>
<router-link :to="{ path:'home' }">Home</router-link>
<router-link :to="{ name:'user',params:{ userId:123 } }"></router-link>
<router-link :to="{ path: 'register', query: { plan: 'private' }}"></router-link>

<router-view/> // 占位符

监听路由变化 watch

1
2
3
4
5
watch:{
'$route': function (newVal, oldVal) {
// newVal.path
}
}

命名路由 vs 命名视图

  • 重命名路由的名称 添加 name 属性
1
2
3
4
5
6
7
8
9
10
11
12
13
14
<router-link :to="?userId=123">User</router-link>
<router-link :to="{ name:'user',params:{ userId:123 }}">User</router-link>
<router-link to="/user/123">/user/123</router-link>
<router-link :to="{ name:'user',params:{ userId:123 }}">User</router-link>

const routes = [
{
path:'/user/:userId'
name:'user', // 命名路由 方便动态绑定传递参数
componet:User
}
]

router.push({ name: 'user', params: { userId: 123 }})
  • 命名视图 同一路由router-view name绑定多个组件 router-view name
1
2
3
4
5
6
7
8
9
10
11
12
13
<router-view />
<router-view name="a"></router-view>
<router-view name="b"></router-view>

const routes:[
{
path:'/',components:{
default:header
a:sidebar, // name名:组件名
b:mainbox
}
}
]

动态路由匹配 某种模式( : )匹配到的所有路由,全部映射到同个组件

  • 动态路径参数:: 同一个组件,不同的路由参数 通过 动态路径参数 渲染出不同的 多个不同组件
  • 同一路由可以匹配多个路由,匹配的优先级就按照路由的定义顺序:谁先定义,谁的优先级就最高(先定义优先级高)
1
2
3
4
5
6
7
8
9
10
routes: [
{ path: '/user/:length/:id', component: () => import('../components/User.vue') }
// 当匹配 /user/:length/:id 这个模式时 导入渲染组件
]

$route.params.length $route.params.id

<router-link to="/user/short/xxx">用户一</router-link>
<router-link to="/user/middle/xxxqiang">用户二</router-link>
<router-link to="/user/long/huaweiqiang">用户三</router-link>

路由元信息 meta 字段

  • 添加路由元信息 meta 字段
  • 定义路由的时候可以配置 meta 字段:
1
2
3
routes: [
{ path: '/bar',component: Bar,metat:{requiresAuth:true} }
]

路由懒加载

  • 当打包构建项目时,JavaScript包会变得非常大,影响页面加载。如果我们能把不同路径对应的组件分割成不同的代码块,然后当路由被访问被访问的时候才加载对应的组件,这样就更加高效了
    实现方式(实现路由组件的懒加载)
1
2
3
4
5
6
7
8
9
10
11
12
13
// 定义一个能够被 Webpack 自动代码分割的异步组件
const Foo = () => import('./Foo.vue')
const router = new VueRouter({
routes: [
{ path: '/foo', component: Foo },
{ path: '/foo', component: () => import('./Foo.vue') }
]
})
把组件按组分块
把某个路由下的所有组件都打包在同个异步块 (chunk) 中。只需要使用命名 chunk
const Foo = () => import(/* webpackChunkName: "group-foo" */ './Foo.vue')
const Bar = () => import(/* webpackChunkName: "group-foo" */ './Bar.vue')
const Baz = () => import(/* webpackChunkName: "group-foo" */ './Baz.vue')

导航守卫 3全局 beforeEach/Resolve/afterEach + 1路由 beforeEnter+ 3组件 beforeRouter + Enter、Update、Leave

  • “导航”表示路由正在发生变化

vue-router 提供的导航守卫主要用来通过跳转或取消的方式守卫导航

  • 全局
    • 前置守卫 router.beforeEach
      • to: Route: 即将要进入的目标 路由对象
      • from: Route: 当前导航正要离开的路由
      • next: Function: 一定要调用该方法来 resolve 这个钩子。执行效果依赖 next 方法的调用参数。
        • next()
        • next(false)
        • next('/')
        • next(error)
    • 解析守卫 router.beforeResolve
    • 后置守卫 router.afterEach
  • 路由守卫 routes路由规则 beforeEnter
  • 组件守卫 Enter、Update、Leave 路由组件内直接定义以下路由导航守卫
    • beforeRouterEnter
    • beforeRouterUpdate
    • beforeRouterLeave

完整的导航解析流程

  1. 导航被触发。
  2. 在失活的组件里调用 beforeRouteLeave 守卫。
  3. 调用全局的 beforeEach 守卫。
  4. 在重用的组件里调用 beforeRouteUpdate 守卫 (2.2+)。
  5. 在路由配置里调用 beforeEnter
  6. 解析异步路由组件。
  7. 在被激活的组件里调用 beforeRouteEnter
  8. 调用全局的 beforeResolve 守卫 (2.5+)。
  9. 导航被确认。
  10. 调用全局的 afterEach 钩子。
  11. 触发 DOM 更新。
  12. 调用 beforeRouteEnter 守卫中传给 next 的回调函数,创建好的组件实例会作为回调函数的参数传入。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
//全局前置守卫 router.beforeEach
router.beforeEach((to,from,next)) =>{
}

router.beforeEach((to,from,next) => {
if(to.name !== ‘Login’ && !isAuthenticated) next({ name:'Login' })
else next()
})
//全局解析守卫 router.beforeResolve

//全局后置钩子 router.afterEach

// 路由独享的守卫 beforeEnter
routes:[
{
path:'/foo',
component:Foo,
beforeEnter:(to,from,next) =>{
// 这些守卫与全局前置守卫的方法参数是一样的
}
}
]
上一页
2022-09-01 00:00:00
下一页