vue-router

  • [ 什么是vue-router ]
  • 传统的路由是针对服务器不同文件,这样路由的变动就会导致新页面加载,导致页面刷新。vue-router 实现了在 vue 组件基础上,不加载页面文件,而是更改部分页面组件的方式来展现不同路由时显示的内容。同时节约了客户端和服务端资源。

  • [ 安装 ]
  •   npm i vue-router@4
    

  • [ 使用 ]
    • vue-router 是通过 hook 的方式获取 router 对象并完成配置,然后以插件的方式挂载到app上面
      // router.js
      import { createRouter, createWebHistory} from 'vue-router'
      import Login from '../components/Login'
      import Register from '../components/Register'
      const routes = [
        {
          path: '/login',
          name: 'Login'
          component: Login
        },
        {
          path: '/register',
          name: 'Register'
          component: Register
        }
      ]
      const router = createRouter({
        history: createWebHistory(),
        routes
      })
      export default router
    
    • 在 main.js 中挂载
      // main.js
      import router from './router'
      app.use(router)
    
    • 在组件中使用路由
      // App.vue
      <router-link to="/login">Login</router-link>
      <router-link to="/register">Register</router-link>
      <hr>
      // router-view 是显示组件的地方,也就是显示 Login 或者 Register 内容的地方
      <router-view></router-view>
    
    • 事件触发跳转
      <template>
        // 方式一 二
        <button @click='toPage('/login')'>Login</button>
    
        // 方式三
        <button @click='toPage('Login')'>Login</button>
      </template>
      <script>
        import { userouter } from 'vue-router' 
        const router = userouter()
    
        // 方式一
        function toPage(url) {
          // 通过 push 方法实现跳转
          router.push(url)
        }
    
        // 方式二
        function toPage(url) {
          // 传入一个对象
          router.push({
            path: url
          })
        }
    
        // 方式三
        function toPage(name) {
          router.push({
            name
          })
        }
      </script>
    

  • [ 路由模式及其不同 ]
    • createWebHistory || createWebHashHistory
    • 如果在login页面里面采用 WebHistory,那么 '/' 路径代表的就是localhost
    • 而如果采用WebHashHistory,那么 '/' 路径代表 localhost/login#/
    • 如果是单页面文件,选择 WebHistory 会简洁一点
    • 如果是多页面文件, WebHashHistory 更容易区分前端路由和后端路由. 当然 WebHistory 也可以,个人更倾向于 WebHistory

  • [ 给路由命名 ]
  •   const routes = [
        {
          path: '/login',
          name: 'Login', // 给路由命名
          component: Login
        },
        {
          path: '/register',
          name: 'Register',
          component: Register
        }
      ]
    
    • 对应的跳转方式
      <router-link :to="{name: 'Login'}">Login</router-link>
    

  • [ 历史记录的处理 ]
  • [ 不加入历史记录 ]
    • 如果页面跳转不想被历史记录 需要加入 replace 属性给 router-link
      <router-link replace to='/login'>Login</router-link>
    
    • 事件跳转不加入历史记录,将 push 方法更变为 replace 方法即可
      router.replace('/login')
    

  • [ 控制页面跳转到历史记录 ]
  •   router.go(n) // 跳转到历史记录向后 n 个记录的页面
      router.back(n) // 跳转到历史记录向前 n 个记录的页面
    

  • [ 如何通过路由传参 ]
    • 通过在 push 或者 replace 方法 中传入的对象里面加入 query 或者 params 属性的方式可以传参
    • 在组件中,通过 router.query.xxx || router.params.xxx 来获取参数

  • [ query ]
    • 这种方式在地址栏的 url 中会携带参数并显示出来
      router.push({
        path: '/info',
        query: item
      })
    
      // info
      <div>Price: {{ router.query.price }}</div>
    

  • [ params ]
    • 这种方式 url 不会携带参数
      router.push({
        name: 'Info',
        params: item
      })
    
      // info
      <div>Price: {{ router.params.price }}</div>
    

  • [ 动态传参 ]
    • 在设定路由的时候,可以添加一个动态参数
      const routes = [
        {
          path: '/detial/:id'
          component: Detial
        }
      ]
    
    • 在传参的时候传入包含对应参数的对象即可
      const id = item.id
      router.push({
        path: '/detial'
        query: {
          id
        }
        // OR
        query: item
      })
    
    • params 方式也可以实现动态传参

  • [ 多级路由嵌套 ]
    • 通过 children 属性来实现路由嵌套
      const routes = [
        {
          path: '/user'
          component: User,
          children: [
            {
              path: 'login' // 注意这里不加 /
              component: Login
            }
          ]
        }
      ]
    

  • [ 命名视图 ]
    • 通过命名视图,一个路径可以对应多个视图组件,并且可以通过名称进行控制
      import Login from '../components/Login'
      import Register from '../components/Register'
      const routes = [
        {
          path: '/login'
          // 这里 component 是一个对象
          component: {
            login: Login
          }
        },
        {
          path: '/register'
          // 这里 component 是一个对象
          component: {
            register: Register
          }
        }
      ]
    
      <template>
        <router-view name='login'></router-view>
        <hr>
        <router-view name='register'></router-view>
      </template>
    

  • [ 重定向 和 别名 ]
  • [ 重定向 redirect ]
  •   const routes = [
        {
          path: '/'
          redirect : '/login'
    
          // OR
          redirect: {
            path:'/login'
          }
    
          // OR
          redirect: to => { // to 是被重定向的路由信息
            return {
              path: '/login'
              query: xxx // 这里可以传参
            }
          }
        },
        {
          path: '/login'
          component: ...
        }
      ]
    

  • [ 别名 alias ]
  •   const routes = [
        {
          path: '/',
          alias: ['/root'] // 这里设置别名后,访问 /root 就相当于访问 /
        }
      ]
    

  • [ 导航守卫 ]
    • 官方链接
    • 所谓导航守卫,就是当网站被访问,或者站内路径改变的时候执行的一些控制代码。
    • 导航守卫有前置和后置之分,前置守卫控制是否进行跳转和预置动作,后置为跳转以后执行的前置代码。
    • 按照作用范围,导航守卫可以分为全局,路径,组件级别。
    • 全局导航守卫
      // jump.js
      export default function(router) {
        router.beforeEach((to, from) => { // afterEach 就是后置守卫
          if(to.name === 'Index' && true) {
            return {name: 'Login'}
          }
        })
    
        router.afterEach((to, from) => {
          if(to.name === 'Index') {
            console.log('oh yeah')
          }
        })
      }
    
    • 页面级别的导航守卫
      {
        path: '/index',
        name: 'Index',
        components: {
          main: Index
        },
        beforeEnter: (to, from) => {
          if(true) {
            return {name: 'Login'}
          }
        }
      }
    
    • 组件内导航守卫,和指定组件的 name 一样,不能使用 setup 语法糖
    <script setup>
      const a = 12
    </script>
    <script>
    export default {
       beforeRouteEnter(to, from, next) {
        if(false) {
          return next({name: 'Login'})
        }
        next()
      }
    }
    </script>
    <template>
      <h1>Index page</h1>
      <p>{{ a }}</p>
    </template>
    <style lang="scss" scoped>
    
    </style>
    

  • [ 路由元信息 ]
    • route 的 meta 属性用来携带路由相关信息
    const routes = [
      {
        path: '/posts',
        component: PostsLayout,
        children: [
          {
            path: 'new',
            component: PostsNew,
            // 只有经过身份验证的用户才能创建帖子
            meta: { requiresAuth: true },
          },
          {
            path: ':id',
            component: PostsDetail
            // 任何人都可以阅读文章
            meta: { requiresAuth: false },
          }
        ]
      }
    ]
    
    • 导航守卫快捷获取 meta 信息
    router.beforeEach((to, from) => {
      // 而不是去检查每条路由记录
      // to.matched.some(record => record.meta.requiresAuth)
      if (to.meta.requiresAuth && !auth.isLoggedIn()) {
        // 此路由需要授权,请检查是否已登录
        // 如果没有,则重定向到登录页面
        return {
          path: '/login',
          // 保存我们所在的位置,以便以后再来
          query: { redirect: to.fullPath },
        }
      }
    })
    
    • router 和 route 在组件中的作用,二者分别可以从vue-router对象的 useRouter 和 useRoute 方法获得实例。
    • router 对象通过其 push 等方法可以添加 meta 并触发页面跳转。
    • route 对象则携带了 meta 数据,通过 route.meta 就可以得到数据。query的方式同理
    • 需要注意的是,params 在通过这种方式传参的时候会报错,不建议使用。

  • [ 过渡动效 ]
  • [ 动态路由 ]
  • posted @ 2024-04-01 11:43  anch  阅读(2)  评论(0编辑  收藏  举报