Vue-Router

101 阅读5分钟

Vue-Router

路由

  • 搭建路由

    • 下包:npm install vue-router@4

      ##### Vue2Vue3路由版本区别
      Vue2:router@3 版本
      Vue3:router@4 版本
      
    • 配置路由表

      • 导入路由

        import {createRouter,createWebHistory,createWebHashHistory} from 'vue-router'
        
      • 配置路由表

        export default createRouter({
            /* history
                    History => 没有#号
                    HashHistory => 带#号
            */
            history:createWebHashHistory(),
            routes:[
                {
                    path:'/home',
                    component:Home // 组件
                },
                {
                    path:'/about',
                    component:About // 组件
                }
            ]
        })
        
    • main.js 中全局引入路由,并声明使用

      • 引入路由

        import router from './router'
        
      • 声明使用

        app.use(router)
        
  • 路由在全局声明使用后

    • 在全局挂载了两个组件

      • <RouterLink></RouterLink>

        • to:路由的路径
        <RouterLink to="/home"></RouterLink>
        
        使用一个自定义组件`<router-link />`来代替`<a />`创建链接
        这使得Vue-Router可以在不重新加载页面的情况下更改URL
        
      • <RouterView></RouterView>

        显示与url对应的组件。你可以把它放在任何地方,以适应你的布局
        
    • 所有组件都可以访问 this.$routerthis.$route

      • this.$router:路由实例对象
      • this.$route:当前路由对象

路由模式

  • createWebHashHistory

    `#`号
    hash使用的window.onhashchange事件来监听URL的路径的变化
    
  • createWebHistory

    不带`#`号
    使用pushState,在不刷新页面的情况下,添加个历史记录
    使用replaceState,在不刷新页面的情况下,替换个历史记录
    使用onpopState,监听的前进和后退
    VueReact路由使用 history 库
    history在上线时,如果进行额外的配置,那么会出现404的问题
    

命名视图

  • 同时 (同级) 展示多个视图,而不是嵌套展示

  • 路由:

    routes:[
        {
            path:"/",
            components:{
                default:Home, // 默认视图
                the:About // 命名视图
            }
        }
    ]
    
  • 使用:

    <RouterView></RouterView> <!-- 显示默认视图 -->
    <RouterView name="the"></RouterView> <!-- 命名视图 -->
    

路由懒加载(性能优化)

  • 路由懒加载:将路由对应的组件打包成一个个的js代码块,只有在这个路由被访问到的时候,才会加载对应组件的代码块
  • 语法:()=>import ('组件路径')
export default createRouter({
    history:createWebHistory(),
    routes:[
        {
            path:'/home',
            component:()=>import ('../views/home.vue')
        },
        {
            path:'/about',
            component:()=>import ('../views/about.vue')
        }
    ]
})

图片懒加载(性能优化)

  • <img src="默认图片" data-src="真的图片">
  • 最开始,使用一张默认的图片,用这种图片展示所有的图片。
  • 当我们滚动条下来的,将能看到的哪几张图片给展示出来,使用真正的图片替换原来的默认的图片
# 后面项目中再讲

命名路由

  • 除了 path 外,可以为路由添加 name

  • 优点:

    • 没有硬编码的 url
    • params 的自动编码/解码
    • 防止你 url 中出现打字错误
    • 绕过路径排序
    // 命名路由
    const routes = [
        {
            path: '/user/:username',
            name: 'user',
            component: User,
        },
    ]
    
    <router-link :to="{ name: 'user', params: { username: 'erina' }}" />
    
    router.push({ name: 'user', params: { username: 'erina' } })
    

路由别名

  • alias:给路由配置多个访问的名称
routes:[
    {
        path:'/home',
        component:News,
        alias:'/hh',
        // alias:['/n','/w','/ws']// 配置多个用数组
    },
    {
        path:'/about',
        component:News,
        alias:['/aa','/bb','/oo','/uu','/tt'],
    }
]

重定向

  • redirect:重定向到哪个路由

    routes:[
        {
            path:'/',
            redirect:'/home'
        }
    ]
    

编程式导航

  • 声明式

    <router-link :to="...">

    <RouterLink to="/home">Home</RouterLink>
    
  • 编程式

    router.push(...)

    使用js实现跳转
    

$router

  • push(路由url):带历史记录的跳转
  • replace(路由url):不带历史记录的跳转
  • forward():前进一页
  • back():后退一页
  • go(n):前进/后退 |n|
  • getRoutes():获取路由表的完整记录
this.$router.push("/home") // 有记录跳转
this.$router.replace("/home") // 无记录跳转
this.$router.forward() // 前进后退
this.$router.back() // 后退
this.$router.go(2) // 前进2页
this.$router.go(-2) // 后退2页
this.$router.getRoutes() // 获取路由表的完整记录
# Vue组合式api
import { useRouter } from "vue-router"; // 引入路由表
let router = useRouter() // 使用

$route

  • path:路径
  • fullpath:全路径
  • query:query参数
  • params:params参数
  • matched:包含当前路由的所有嵌套路径片段的路由记录 。路由记录就是 routes 配置数组中的对象副本 (还有在 children 的数组)
# Vue组合式api
import { useRoute } from "vue-router"; // 引入路由对象
let route = useRoute() // 使用

路由传参

query参数

  • 语法1:字符串、参无

    this.$router.push('/home')
    
  • 语法2:字符串、带query参数

    this.$router.push('/home?name=张三&age=18&gender=男')
    
  • 语法3:对象、无参

    this.$router.push({path:'/home'})
    
  • 语法4:对象、带query参数

    this.$router.push({path:'/home',query:{name:'张三',age:18,gender:'男'}})
    
  • 语法5:对象、使用name、无参

    this.$router.push({name:'home'})
    
  • 语法6:对象、使用name、带query参数

    this.$router.push({name:'home',query:{name:'张三',age:18}})
    

params参数

  • 语法1:字符串、params参数、借助路由表

    this.$router.push("/home/张三/18")
    
  • 语法2:对象、params参数

    this.$router.push({ path: '/home', params: { name: "张三", age: 18, gender: '男' } })
    
    `!注意:params与path不能一起共用,否则params失效`
    
  • 语法3:综合

    this.$router.push({ name: 'home', query: { username: "张三" }, params: { age: 18 } })
    
`指定params参数可传可不传`
// 在参数后加`?`号
// 例:路由表中:
{
    path:'/home/:id?'
}

嵌套路由

  • 语法1:

    // 一级路由
    routes:[
        {
            path:'/home',
            component:Movie,
            // 二级路由
            children:[
                {
                    path:'/home',
                    redirect:'/home/list'
                },
                {
                    path:'/home/list',
                    component:List
                },
                {
                    path:"/home/about",
                    component:About
                }
            ]
        },
    ]
    
  • 语法2:

    // 一级路由
    routes:[
        {
            path:'/home',
            component:Movie,
            // 二级路由
            children:[
                {
                    path:'list',
                    component:List
                },
                {
                    path:"about",
                    component:About
                }
            ]
        },
    ]
    

导航守卫

  • 导航守卫:路由跳转的保安

  • 全局导航守卫

    * 但凡有路由跳转,都会触发
    * 书写位置:在路由表中与`createRouter`平级
    
    • beforeEach(全局前置守卫)
    • afterEach (全局后置守卫) 参数 next 无效果
    • beforeResolve (全局解析守卫) 用不到
    🌰:
    router.beforeEach((to,from,next)=>{
        console.log("全局前置守卫:",to,from);
        next() // 放行
    })
    router.afterEach((to,from,next)=>{
        console.log("全局后置守卫:",to,from);
        next() // 放行
    })
    
  • 路由独享守卫

    • beforeEnter

      * 在当前路径下跳转进行拦截,专门针对某一个路由
      * 书写位置:路由表内
      
      🌰:
      const router = createRouter({
      	history: createWebHistory(),
      	{
      	path:'/home/list',
      	component:List,
              beforeEnter:(to,from)=>{
                  console.log("路由独享守卫:",to,from);
              }
      	}
      })
      
  • 组件内守卫

    • beforeRouterEnter:跳转到组件之前,注意: 不能使用 this
    • beforeRouterUpdate:当前组件跳转自己(路由的参数发生改变)触发
    • beforeRouterLeave:组件离开触发
    * 书写位置:组件内与`选项`平级
    
    🌰:
    //跳转该组件之前
    beforeRouteEnter(to,from,next){
        console.log("组件跳转之前:",to,from);
        next();
    },
    //组件跳转自己,路由参数发生改边
    beforeRouteUpdate(to,from){
        console.log("跳转自己:",to,from);
    },
    //组件离开
    beforeRouteLeave(to,from){
    	console.log("组件离开:",to,from);
    }
    
  • 导航守卫的形参

    • to:跳转目标

    • from:跳转来源

    • next:拦截/放行

      • next() , next(true) => 放行
      • next(路由url) => 强制跳转url路径
      • next(false) => 拦截
      ##### Vue2Vue3在导航守卫中形参 next 的区别
      Vue2next(),next(true) => 放行
          next(路由url) => 强制跳转路径
          next(false) => 拦截
      Vue3:
      	next选填,如果没写next,那就return替换next
      	默认没写return,表示放行
      	return true => 放行
      	return false => 拦截
      	return 路由url => 强制跳转url地址
      

路由元信息

  • 希望将任意信息附加到路由上,如过渡名称、谁可以访问路由等
  • 可以通过接收属性对象的 meta 属性来实现
🌰:
const routes = [
    {
        path: '/home',
        component: Home,
        // 只有经过身份验证的用户才能创建帖子
        meta: { requiresAuth: true }
    }
]

滚动行为

  • 路由跳转,始终滚动到顶部

    * 书写位置:路由表中与`routes`平级
    
    scrollBehavior(to, from, savedPosition) {
        return { top: 0 }
    }