Vue-router

单页面应用程序 SPA

单页面应用程序将所有的功能局限于一个 web 页面中,仅在该 web 页面初始化时加载相应的资源( HTML、JavaScript 和 CSS)。 一旦页面加载完成了,SPA 不会因为用户的操作而进行页面的重新加载或跳转。而是利用 JavaScript 动态地变换 HTML 的内容,从而实现页面与用户的交互。

SPA 的优点:

  • 良好的交互体验

    • 内容的改变不需要重新加载整个页面

    • 数据通过 Ajax 异步获取

    • 没有页面跳转,不会出现白屏现象

  • 良好的前后盾工作分离模式

    • 后端专注于提供 API 接口,更易实现接口复用

    • 前端专注页面渲染,更利于前端工程化发展

  • 减轻服务器压力

    • 服务器只提供数据,不负责页面的合成与逻辑处理,吞吐能力会提高

SPA 的缺点:

  • 首屏加载慢:可使用路由懒加载、代码压缩、CDN 加速、网络传输压缩

  • 不利于 SEO :SSR 服务器端渲染

vue-router 初体验

安装 vue-router

npm install vue-router@3.5.2 -S

创建路由模块,在 src 源代码目录下,新建 router/index.js 路由模块,初始化代码:

import Vue from 'vue'
import VueRouter from 'vue-router'
import Home from '@/component/Home.vue'
import About from '@/component/About.vue'
import Movie from '@/component/Movie.vue'
​
// 把 VueRouter 安装为 Vue 的插件
Vue.use(VueRouter)
​
// 路由匹配规则
const routes = [
  { path: '/home', component: Home },
  { path: '/about', component: About },
  { path: '/movie', component: Movie },
]
​
// 创建路由实例对象
const router = new VueRouter({
  routes,
})
​
export default router

main.js 文件中导入并挂载路由模块:

import Vue from 'vue'
import App from './App.vue'
import router from './router/index.js'
​
new Vue({
  router,
  render: (h) => h(App),
}).$mount('#app')

在组件中声明路由链接和占位符:

<template>
  <div class="app-container">
    <!-- 路由链接 -->
    <router-link to="/home">首页</router-link>
    <router-link to="/about">关于</router-link>
    <router-link to="/movie">电影</router-link>
​
    <!-- 路由出口 -->
    <router-view></router-view>
  </div>
</template>

注意事项:

  • 组件分为路由组件和一般组件,前者放在 views(或pages) 文件夹,后者放在 components 文件夹

  • 每个组件都有 $route 属性,存储着组件的路由规则信息 通过 $route.push 可以拿到哈希值

  • $router 是路由器对象,整个 SPA 只有一个

声明式导航

<router-link> 4 个常用属性:

  1. to 属性

  • 用于指定跳转路由

<router-link to="/about"></router-link>
  1. tag 属性

  • 指明 <router-link> 最终被渲染为何种标签,默认是 a 标签

  • 渲染为其他标签也会监听点击,触发导航

<router-link to="/about" tag="li">tag</router-link>
//页面渲染结果
<li>tag</li>
  1. replace 属性

  • 路由跳转不会增加新的历史记录,而是替换当前历史记录

<router-link to="/about" replace>About</router-link>
  1. active-class 属性

  • 指明路由被激活时添加的类名,默认为 router-link-active

  • 详见路由高亮

<router-link to="/about" active-class="active">About</router-link>

路由高亮

  • RouterLink会自动给当前的链接添加两个类名

  • router-link-active: 激活的导航链接 模糊匹配

  • router-link-exact-active: 激活的导航链接 精确匹配

  • exact: 必须要精确匹配

被激活的路由链接,默认会添加 router-link-activerouter-link-exact-active的类名。可据此为激活的路由链接设置高亮的样式:

.router-link-active {
  color: white;
  background-color: pink;
}

定义路由模块时可以修改默认高亮的类名类名:

const router = new VueRouter({
  // 默认的 router-link-active 会被覆盖
  linkActiveClass: 'active-hello',
  linkExactActiveClass: 'active',
})

路由重定向

const routes = [
  // 访问 / 跳转到 /home
  { path: '/', redirect: '/home' },
  { path: '/home', component: 'Home' },
  { path: '/about', component: 'About' },
  { path: '/movie', component: 'Movie' },
]
​
const router = new VueRouter({
  routes,
})
​
export default router

嵌套路由

About 组件中声明子路由链接和子路由占位符:

<template>
  <div class="about-container">
    <!-- 要把父路由寫上 -->
    <router-link to="/about/tab1">tab1</router-link>
    <router-link to="/about/tab2">tab2</router-link>
​
    <router-view></router-view>
  </div>
</template>

通过 children 属性声明子路由规则:

const routes = [
  {
    path: '/about',
    component: 'About',
    children: [
      { path: 'tab1', component: Tab1 },
      { path: 'tab2', component: Tab2 },
    ],
  },
]

编程式导航

声明式导航:

  • 通过点击链接实现导航

  • 如普通网页点击 a 链接,vue 点击 <router-link>

编程式导航:

  • 通过调用 API 实现导航

  • 普通网页通过 location.href 的方式跳转页面也是编程式导航

vue-router 中实现编程式导航的 API :

  • this.$router.push('hash地址') :跳转到指定页面,并增加一条历史记录

  • this.$router.replace('hash地址') :跳转页面,但不会新增历史记录,而是替换当前的历史记录

  • this.$router.go(数值) :历史记录前进或后退,相当于点击浏览器前进后退箭头

  • this.$router.forward() :前进一步

  • this.$router.back() :后退一步

$router与$route

  • $router:路由的实例化对象,主要用于路由的跳转

  • $route:用于获取当前路由的基本信息

    • 比如路由的传参,路由的path之类

路由传参

  • $route对象中的属性参数

  • 在 hash 地址中,/后面的参数项,叫做 '路径' ,可以通过 this.$route.params 来访问 路径参数

  • 在 hash 地址中,后面的参数项,叫做 ‘查询参数’ ,可以通过 this.$route.query 来访问 查询参数

  • 在 this.$route 中,path只是路径部分, fullPath 是完整的地址(包括 路径和查询参数)

query参数

    • this.$router.push('/xxx?参数名=值')

    • this.$router.push({path:'/xxx',query:{参数名:值}})

    • this.$route.query.参数名

传 
 this.$router.push('/play?id=' + id)
 this.$router.push(`/home/detail?id=${id}&title=${title}`)
 this.$router.push({ path: '/home/detail', query: { id: 1, title: '你干嘛' } })
-------------------------------------------------------------------------------
收
this.$route.query.id
this.$route.query.title

params 参数(动态路由)

  • 动态路由是把 Hash 地址中可变的部分定义为参数项,从而提高路由规则的复用性。

  • 动态参数后面的 如果不加 ?代表必须要传参,? 代表可传可不传

  • params:动态路由匹配

    • 路由配制

{
  path:'/xxx/:id?',component:()=>import ('@/views/xxx.vue')
}
    • this.$router.push('/xxx/123')

    • this.$route.params.id

传
this.$router.push(`/movie/1/21/id=${id}`)
this.$router.push({ name: 'movie', params: { id: 1, age: 21 }, query: { school: 'love' } })
收
-------------------------------------------------------
<template>
  <div class="movie-container">
    <h1>Movie组件,参数值:{{ $route.params.id }}</h1>
  </div>
</template>

动态参数使用场景

// 定义动态路由参数,此时只要写一个路由规则就可以匹配多个导航
{ path: '/movie/:id/:msg', component: ()=>import('@/views/move') }
---------------------------------------------------------------------
如果有路由组件在一个路由参数的不同的情况下要显示不同的页面,就可以使用动态参数
<router-link to="/movie/1/快点亲亲我吖"></router-link>
<router-link to="/movie/2/小蔡头喵喵喵"></router-link>
<router-link to="/movie/3/香草少女"></router-link>

props接收参数(了解)

{ path: '/movie/:mid', component: ()=>import('@/views/move'), query:true}
---------------------------------------------------------------------
如果有路由组件在一个路由参数的不同的情况下要显示不同的页面,就可以使用动态参数
<router-link to="/movie/1"></router-link>
<router-link to="/movie/2></router-link>
<router-link to="/movie/3></router-link>
当我切换不同的导航时,想要拿到动态id的值
我们可以通过 this.$route.params.id 拿到 
-------------------------------------------
movie组件中 通过
声明:props:['mid']
然后通过 this.mid 拿到 ,在标签中可以通过 {{mid}} 拿到 
注意:如果想通过这种方式拿到 需要在路由规则中 开启  query:true

路由的补充

路由元

  • 配制路由时加入meta:{key:值}

{
 path:'/xxx',
 component:...,
 meta:{
    title:标题,
    xxx:....
 }
}
  • 路由元可以通过当前路由的this.$route.meta获取到

    • 比如:this.$route.meta.title

使用方法

 // 在当前路由页面使用 
 created(){
    document.title=this.$route.meta.title
  },

路由 - 模式设置

目标: 修改路由在地址栏的模式

hash路由例如: http://localhost:8080/#/home

history路由例如: http://localhost:8080/home (以后上线需要服务器端支持)

不同的历史模式 | Vue Router服务器配置示例

router/index.js

const router = new VueRouter({
  routes,
  mode: "history" // 打包上线后需要后台支持, 默认是hash
})

alias:别名

{
   path:'/',
   alias:'/home' // 别名  飞哥  董浩飞
   // 上面二路由path是一样的了
}

路由配制的二种path写法

{
  path: '/layout',
  // alias: '/', // 路由别名
  // redirect: '/',
  component: Layout,
  children: [
    {
      path: '/layout/home',
      component: Home
    },
     
    {
       这样写和上面的写法一样
      path: 'user',
      component: User
    },
    {
      path: 'permission',
      // path以开头的叫绝对写法,意思 :写什么路由的path是什么最后就是什么   /xxx===/xxx
      // path也可以不以/开头,这种叫相对写法,相对于自己的父级path   xxx===/layout/xxx
      component: Permission
    }
  ]
}

路由配制的components写法

​
<router-view  name="default" />
<router-view  name="xxx" />
​
{
  path:'/xxx',
  component:xxx组件
  等效于
  components:{
     default:default的组件
     xxx:xxx组件
     // 实际很少用,了解就可以了
  }
}

路由守卫

作用:对路由进行权限控制。

分类:全局守卫、独享守卫、组件内守卫

全局守卫

  • 全局前置守卫:beforeEach()

  • 全局后置守卫:afterEach()

守卫回调函数 3 个形参:

  • to :将要访问的路由的信息对象,即 $route

  • from :将要离开的路由的信息对象

  • next :放行函数(后置守卫没有)

next 函数 3 种调用方式:

  • 直接放行:next()

  • 强制跳转到其他路由:next(/login)

  • 阻止本次跳转:next(false)

const router = new VueRouter({...})
​
router.beforeEach((to, from, next) => {
  if(to.path === '/main') {
    const token = localStorage.getItem('token')
​
    if(token) {
      next()
    } else {
      next('/login')
    }
  } else {
      next()
  }
})
​
router.afterEach((to,from) => {
  if(to.meta.title) {
    // 修改网页标题
    document.title = to.meta.title
  } else {
    document.title = 'vue_test'
  }
})

独享路由守卫

  • 某一条路由规则独享的守卫

  • 独享守卫只一个

{
  path: 'about',
  component: About,
  beforeEnter(to, from ,next) {
    ...
  }
}

组件内路由守卫

export default {
  name: 'About',
​
  // 进入守卫:通过路由规则,进入该组件时被调用
  beforeRouteEnter(to, from, next) {
    ...
  }
​
  // 离开守卫:通过路由规则,离开该组件时被调用
  beforeRouteLeave (to, from, next) {
    ...
  }
}

各个守卫执行顺序

About 组件通过路由规则进入 Home 组件:

About-beforeRouteLeave
beforeEach
Home-beforeEnter
Home-beforeRouteEnter
afterEach
Home组件生命周期开始

  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值