VueRouter基本使用宝典

VueRouter

vue-router用法大全

使用了一段时间 Vue2 + Vuex + VueRouter + Element UI 开发之后

发现仅仅只用到了VueRouter的少数浅层功能 大部分高级功能都没有用到 决定看官方文档学习一下

官方文档是最好的学习笔记(●’◡’●)

API 参考 | Vue Router (vuejs.org)

VueRouter参数配置大全

参数类型默认值可选值描述
routesArray配置路由规则
modestring“hash” (浏览器环境) /“abstract” (Node.js 环境)“hash”/“history” / “abstract”配置路由模式
basestring/应用的基路径
linkActiveClassstringrouter-link-exact-active全局配置 默认的精确激活的 class
scrollBehaviorFunction配置滚动行为
parseQuery / stringifyQueryFunction提供自定义查询字符串的解析/反解析函数
fallbackboolean当浏览器不支持 history.pushState 控制路由是否应该回退到 hash 模式。默认值为 true
// 引入 vue-router
import VueRouter from "vue-router";
import Vue from 'vue'
Vue.use(VueRouter)

// 创建  一个路由器
const router = new VueRouter({
    routes:[],
    // 匹配模式设置
    mode:"",
    base:"",
    // 配置路由被激活时使用的 CSS类名称
    // 此时使用 .active{color:blue} 等...
    linkActiveClass: 'active',

    // 这个功能只在支持 history.pushState 的浏览器中可用
    scrollBehavior (to, from, savedPosition) {
        // return 期望滚动到哪个的位置
    }
    
    parseQuery: function(){},
    stringifyQuery: function(){},
    
    // 当浏览器不支持 history.pushState 控制路由是否应该回退到 hash 模式。默认值为 true
    fallback:true,
})

// 暴露该路由器
export default router

Mode参数详解

//hash: 使用 URL hash 值来作路由。支持所有浏览器,包括不支持 HTML5 History Api 的浏览器。

//history: 依赖 HTML5 History API 和服务器配置。查看 HTML5 History 模式。

//abstract: 支持所有 JavaScript 运行环境,如 Node.js 服务器端。如果发现没有浏览器的 API,路由会自动强制进入这个模式。

scrollBehavior参数详解

使用前端路由,当切换到新路由时,想要页面滚到顶部,或者是保持原先的滚动位置,就像重新加载页面那样。 vue-router 能做到,而且更好,它让你可以自定义路由切换时页面如何滚动。

scrollBehavior 函数接收 to from 路由对象,如 Navigation Guards。第三个参数 savedPosition,只有当这是一个 popstate 导航时才可用(由浏览器的后退/前进按钮触发)。

// 该函数可以返回一个 ScrollToOptions 位置对象:
scrollBehavior (to, from, savedPosition) {
    // return 期望滚动到哪个的位置

    // 1.
    // 始终滚动到顶部
    return { top: 0 }
    // 跳转到 x y 的坐标
    return {x:0, y:0}

    // 2.
    // 你也可以通过 el 传递一个 CSS 选择器或一个 DOM 元素。在这种情况下,top 和 left 将被视为该元素的相对偏移量。
    // el: document.getElementById('main'),
    return {
        // 始终在元素 #main 上方滚动 10px
        el: '#main',
        top: -10,
    }

    // 3.
    // 如果返回一个 falsy 的值,或者是一个空对象,那么不会发生滚动
    // falsy js中所有表达式判断为 false 的值
    return false

    // 4. 
    // 如果你要模拟 “滚动到锚点” 的行为
    if (to.hash) {
        return {
            el: to.hash,
            // 如果你的浏览器支持滚动行为,你可以让它变得更流畅
            // 支持 Window.scroll()
            behavior: 'smooth',
        }
    }

    // 5.
    // 延迟滚动
    return new Promise((resolve, reject) => {
        setTimeout(() => {
            resolve({ left: 0, top: 0 })
        }, 500)
    })
}

parseQuery stringifyQuery参数详解

  • stringifyQuery: 序列化传入的query参数,方法可以接收一个对象参数

    new Router的时候传递这个属性,在序列化query参数的就执行这个方法,不会执行默认的方法,序列化后在地址栏显示序列化之后的参数

  • parseQuery: 解析地址栏参数,方法接收一个字符串参数

    new Router的时候传递这个属性,在解析query参数的时候,会执行这个方法,不会在执行默认的方法,

这个方法只解析path中的参数,或者浏览器刷新的时候的地址栏的参数,不会对在query参数对处理

this.$router.push({
    path: "url?name=snowman",
    query: {
        password: "qwkejqowr"
    }
})
// 简单写一下加密
stringifyQuery(obj){
    const res = obj ? Object.keys(obj).map(key => {
        const val = obj[key]
        if (val === undefined) {
            return ''
        }
        if (val === null) {
            return encode(key)
        }
        return encode(key) + '=' + encode(val)
    })
    return res
}

Routes参数详解

interface RouteConfig = {
  path: string,
  component?: Component,
  name?: string, // 命名路由
  components?: { [name: string]: Component }, // 命名视图组件
  redirect?: string | Location | Function,
  props?: boolean | Object | Function,
  alias?: string | Array<string>,
  children?: Array<RouteConfig>, // 嵌套路由
  beforeEnter?: (to: Route, from: Route, next: Function) => void,
  meta?: any,
  // 2.6.0+
  caseSensitive?: boolean, // 匹配规则是否大小写敏感?(默认值:false)
  pathToRegexpOptions?: Object // 编译正则的选项
}
属性详解
path路径
name命名路由
component命名视图组件
components命名视图组件
redirect重定向路径
alias别名
children嵌套路由
meta路由元信息 使用$route.meta.属性可以获取
caseSensitive匹配规则是否大小写敏感?(默认值:false)
pathToRegexpOptions编译正则的选项
props组件路由传参
path参数详解
const routes = [
    // 1.
    // 匹配 /p/books
    // 使用 : 开头代表需要传递参数
    // this.route.parmas.orderId 获取
    { path: '/p/:productName' },
    // * 表示匹配全部路由
    { path:"*", },
    


    // 2.
    // 在参数中自定义正则
    // 匹配 /o/3549 仅匹配数字
    { path: '/o/:orderId(\\d+)' },


    // 3.
    // 可重复的参数
    // /:chapters ->  匹配 /one, /one/two, /one/two/three, 等
    { path: '/:chapters+' },
    // /:chapters -> 匹配 /, /1, /1/2, /1/2/3, 等
    { path: '/:chapters(\\d+)*' },


    // 4.
    // 将匹配 /users/posva 而非:
    // 对 大小写 敏感
    // - /Users/posva 当 sensitive: true
    { path: '/users/:id', sensitive: true },

    // 对url末尾的 / 敏感
    // - /users/posva/ 当 strict: true
    // 将匹配 /users, /Users, 以及 /users/42 而非 /users/ 或 /users/42/
    { path: '/users/:id?' },



    // 5.
    // 可选参数
    // 请注意,* 在技术上也标志着一个参数是可选的,但 ? 参数不能重复。
    // 匹配 /users 和 /users/posva
    { path: '/users/:userId?' },
    // 匹配 /users 和 /users/42
    { path: '/users/:userId(\\d+)?' },
]
// 官方API文档里没有给出这两个参数 有点疑惑
strict: true
sensitive: true
name参数详解

1.渲染组件

{
    path:"/",
    component:MainPage,
    // 定义name
    name:"RouteName"
}
<template>
  <div id="app">
     <router-view></router-view>
      <!-- 将渲染MainPage组件 -->
     <router-view  name="RouteName"></router-view>
  </div>
</template>

2.可以用name传参 使用$route.name获取组件name值

this.$route.name

3.router-link 使用pramas传参必须使用name跳转

<router-link :to="{name:'RouteName',params:{name:'Snowman'}}">ToMainPage</router-link>
component参数详解
{
    path:"BlogContent",
    // 可以使用函数的方式进行懒加载
    component: component: () => import('../views/MusicPlay')
    
    // 也可直接 import后 在此处使用
    component: ComponentObject
    
    // 在项目开发中应用中不需要一开始就加载的路由组件请使用懒加载
    // 路由的懒加载,通过函数的形式,可以让项目中哪些不许一开始就要加载的组件,加载到项目中去
    // 只有浏览器跳转到当前路由时,该路由组件才会加载到项目中去
    // 这样做的好处是减少不必要的加载降低应用加载速度和运行带宽
},

components参数详解

有时候想同时 (同级) 展示多个视图,而不是嵌套展示,例如创建一个布局,有 sidebar (侧导航) 和 main (主内容) 两个视图,这个时候命名视图就派上用场了。你可以在界面中拥有多个单独命名的视图,而不是只有一个单独的出口。如果 router-view 没有设置名字,那么默认为 default

routes = {
    path: '/',
    components: {
        default: Home,
        // LeftSidebar: LeftSidebar 的缩写
        LeftSidebar,
        // 它们与 `<router-view>` 上的 `name` 属性匹配
        RightSidebar,
    }
<!-- 展示Components中配置的组件 -->
<router-view class="view left-sidebar" name="LeftSidebar"></router-view>
<router-view class="view main-content"></router-view>
<router-view class="view right-sidebar" name="RightSidebar"></router-view>
redirect参数详解
// 可以使用路径重定向
const routes = [{ path: '/home', redirect: '/' }]
// 不带 / 为相对路径的跳转
const routes = [{ path: '/home', redirect: 'next' }]

// 可以使用路由名称重定向
const routes = [{ path: '/home', redirect: { name: 'homepage' } }]

// 可以是一个方法
// 低配版路由守卫
redirect: to => {
      // 方法接收目标路由作为参数
      // return 重定向的字符串路径/路径对象
      return { path: '/search', query: { q: to.params.searchText } }
    },
alias参数详解
const routes = [{ path: '/home', redirect: '/' }]

重定向是指当用户访问 /home 时,URL 会被 / 替换,然后匹配成 /。那么什么是别名呢?

/ 别名为 /home,意味着当用户访问 /home 时,URL 仍然是 /home,但会被匹配为用户正在访问 /

// 与rediect的区别就是 URL 是否变化
// 定位到 /home 时 
// 显示为 /home 但是访问的是 /
const routes = [{ path: '/', component: Homepage, alias: '/home' },
                // 可以使用数组提供多个别名
                // 绝对相对均可
               { path: '', component: UserList, alias: ['/people', 'list', ''] },
                // 路由有参数必须使用 绝对URL
               { path: '/', component: Homepage, alias: '/:id' },]
meta参数详解
  • meta的定义:简单来说就是路由元信息,也就是每个路由身上携带的信息。
  • meta的作用:vue-router路由元信息说白了就是通过meta对象中的一些属性来判断当前路由是否需要进一步处理,如果需要处理,按照自己想要的效果进行处理即可

我们称呼 routes 配置中的每个路由对象为 路由记录。路由记录可以是嵌套的,因此,当一个路由匹配成功后,他可能匹配多个路由记录

let routes = [
    {
        path: '/foo',
        component: Foo,
        children: [
            {
                path: 'bar',
                component: Bar,
                // 配置 requiresAuth: true
                // 只有经过身份验证的用户才能访问该内容
                meta: {
                    requiresAuth: true,
                    title: "路由标题 在HTML中展示什么"
                }
            }
        ]

一个路由匹配到的所有路由记录会暴露为 $route 对象(还有在导航守卫中的路由对象)的$route.matched 数组。我们需要遍历这个数组来检查路由记录中的 meta 字段,但是 Vue Router 还为你提供了一个 $route.meta 方法,它是一个非递归合并所有 meta 字段的(从父字段到子字段)的方法。这意味着你可以简单地写

// $route.matched 数组为子与父路由的全部 meta信息组成的数组
router.beforeEach((to, from) => {
  // 而不是去检查每条路由记录
  // some方法遍历数组 如果满足 return条件 为ture 则返回 否则为false
  // to.matched.some(record => record.meta.requiresAuth)
  if (to.meta.requiresAuth && !auth.isLoggedIn()) {
    // 此路由需要授权,请检查是否已登录
    // 如果没有,则重定向到登录页面
    return {
      path: '/login',
      // 保存我们所在的位置,以便以后再来
      query: { redirect: to.fullPath },
    }
  }
})
caseSensitive参数详解

是否严格匹配大小写

false:严格匹配

ture:大小写均可匹配

props参数详解
简单案例
// router/index.js 简单示例
// 引入 vue-router
import VueRouter from "vue-router";
import Vue from 'vue'
Vue.use(VueRouter)
// 引入组件
import BlogMainPage from "@/components/BlogPage/BlogMainPage";
// 引入加载动画
import NProgress from 'nprogress'
import 'nprogress/nprogress.css'

// 创建  一个路由器
const router = new VueRouter({
    routes: [
        {
            path:"/",
            component:MainPage,
        },
        {
            path:"/BlogMainPage",
            component:BlogMainPage,
            children:
            [
                {
                    path:"BlogContent",
                    component: BlogContent
                },
            ]
        },
        {
            // :id 可进行路由传参 在 this.$route.params.id 获取
            path:"/BlogDetail/:id",
            component:BlogDetail
        },
        {
            path:"*",
            component:PageNotFound,
        }
        // path 为 * 表示匹配全部 可以匹配全部路径 路径匹配为从上至下
    ]
})

// 配置加载条 nprogress 以及加载动画
router.beforeEach((to, from, next) => {
    NProgress.start()
    next()
})
router.afterEach(() => {
    NProgress.done()
})

// 暴露该路由器
export default router

路由守卫

官方文档:https://router.vuejs.org/zh/guide/advanced/navigation-guards.html

正如其名,vue-router 提供的导航守卫主要用来通过跳转或取消的方式守卫导航。这里有很多方式植入路由导航中:全局的,单个路由独享的,或者组件级的。

全局前置守卫

// 在路由跳转之前调用
router.beforeEach((to, from) => {
  // ...
  // 返回 false 以取消导航
  return false
})

当一个导航触发时,全局前置守卫按照创建顺序调用。守卫是异步解析执行,此时导航在所有守卫 resolve 完之前一直处于等待中

每个守卫方法接收两个参数:

均为 RouteLocationNormalized 对象: API 参考 | Vue Router (vuejs.org)

  • to: 即将要进入的目标
  • from: 当前导航正要离开的路由

可以返回的值如下:

  • false: 取消当前的导航。如果浏览器的 URL 改变了(可能是用户手动或者浏览器后退按钮),那么 URL 地址会重置到 from 路由对应的地址。
  • 一个路由地址: 通过一个路由地址跳转到一个不同的地址,就像你调用 router.push() 一样,你可以设置诸如 replace: truename: 'home' 之类的配置。当前的导航被中断,然后进行一个新的导航,就和 from 一样。
// 在路由跳转之前 可判断用户是否登录
router.beforeEach(async (to, from) => {
   if (
     // 检查用户是否已登录
     !isAuthenticated &&
     // ❗️ 避免无限重定向
     to.name !== 'Login'
   ) {
     // 将用户重定向到登录页面
     return { name: 'Login' }
   }
 })

如果遇到了意料之外的情况,可能会抛出一个 Error。这会取消导航并且调用 router.onError() 注册过的回调。

如果什么都没有,undefined 或返回 true则导航是有效的,并调用下一个导航守卫

以上所有都同 async 函数 和 Promise 工作方式一样:

可选的第三个参数 next

确保 next 在任何给定的导航守卫中都被严格调用一次!!!!

// GOOD
router.beforeEach((to, from, next) => {
  if (to.name !== 'Login' && !isAuthenticated) next({ name: 'Login' })
  else next()
})

全局解析守卫

你可以用 router.beforeResolve 注册一个全局守卫。这和 router.beforeEach 类似,因为它在 每次导航时都会触发,但是确保在导航被确认之前,同时在所有组件内守卫和异步路由组件被解析之后,解析守卫就被正确调用。这里有一个例子,确保用户可以访问自定义 meta属性 requiresCamera 的路由:

// 不是很能理解这个钩子 等遇到相关需求的时候再看
router.beforeResolve(async to => {
  if (to.meta.requiresCamera) {
    try {
      await askForCameraPermission()
    } catch (error) {
      if (error instanceof NotAllowedError) {
        // ... 处理错误,然后取消导航
        return false
      } else {
        // 意料之外的错误,取消导航并把错误传给全局处理器
        throw error
      }
    }
  }
})

全局后置钩子

你也可以注册全局后置钩子,然而和守卫不同的是,这些钩子不会接受 next 函数也不会改变导航本身:

router.afterEach((to, from) => {
  alert(to.fullPath)
})

// 可选参数 failure 判断路由是否跳出
router.afterEach((to, from, failure) => {
  if (!failure) sendToAnalytics(to.fullPath)
})

路由独享的守卫

const routes = [
    {
        path: '/users/:id',
        component: UserDetails,
		// 可在 配置时 直接给该路由配置单独的路由守卫
        beforeEnter: (to, from) => {
            // reject the navigation
            return false
        },
        // 也可以使用数组的形式 依次访问
        beforeEnter: [removeQueryParams, removeHash],
    },
]

router link 与 view

以下内容 从官方文档CV 建议直接看文档

这部分都比较好理解

API 参考 | Vue Router (vuejs.org)

router-link参数

to
<!-- 使用URL跳转 -->
<router-link to="/home">Home</router-link>
<!-- 渲染结果 -->
<a href="/home">Home</a>

<!-- 使用 v-bind 的 JS 表达式 -->
<router-link :to="'/home'">Home</router-link>

<!-- 同上 -->
<!-- 对象配置 to -->
<router-link :to="{ path: '/home' }">Home</router-link>

<!-- 命名的路由 -->
<router-link :to="{ name: 'user', params: { userId: '123' }}">User</router-link>

<!-- 带查询参数,下面的结果为 `/register?plan=private` -->
<router-link :to="{ path: '/register', query: { plan: 'private' }}">
  Register
</router-link>
replace
  • 类型boolean

  • 默认值false

  • 详细内容

    设置 replace 属性的话,当点击时,会调用 router.replace(),而不是 router.push(),所以导航后不会留下历史记录。

<router-link to="/abc" replace></router-link>
active-class
  • 类型string

  • 默认值"router-link-active" (或者全局 linkActiveClass)

  • 详细内容

    链接激活时,应用于渲染的 <a> 的 class。

custom
  • 类型boolean

  • 默认值false

  • 详细内容

    <router-link> 是否应该将其内容包裹在 <a> 元素中。在使用 v-slot 创建自定义 RouterLink 时很有用。默认情况下,<router-link> 会将其内容包裹在 <a> 元素中,即使使用 v-slot 也是如此。传递自定义的 prop,可以去除这种行为。

  • 例如

    <router-link to="/home" custom v-slot="{ navigate, href, route }">
      <a :href="href" @click="navigate">{{ route.fullPath }}</a>
    </router-link>
    

    渲染成 <a href="/home">/home</a>

    <router-link to="/home" v-slot="{ route }">
      <span>{{ route.fullPath }}</span>
    </router-link>
    

    渲染成 <a href="/home"><span>/home</span></a>

exact-active-class
  • 类型string

  • 默认值"router-link-exact-active" (或者全局 linkExactActiveClass)

  • 详细内容

    链接精准激活时,应用于渲染的 <a> 的 class。

v-slot

可以将 渲染后的a标签包裹在内部

router-view参数

name
  • 类型string

  • 默认值"default"

  • 详细内容

    如果 <router-view> 设置了 name,则会渲染对应的路由配置中 components 下的相应组件。

  • 详情见 compoents配置

route

(我直接看不懂这个 不理解)

  • 类型RouteLocationNormalized

  • 详细内容

    一个路由地址的所有组件都已被解析(如果所有组件都被懒加载),因此可以显示。

v-slot

<router-view> 暴露了一个 v-slot API,主要使用 <transition><keep-alive> 组件来包裹你的路由组件。

示例:

<!-- Component为路由对应的组件 -->
<!-- route 为 route对象 可在官方文档查阅 -->
<router-view v-slot="{ Component, route }">
  <transition :name="route.meta.transition || 'fade'" mode="out-in">
    <keep-alive>
      <suspense>
        <template #default>
          <component
            :is="Component"
            :key="route.meta.usePathKey ? route.path : undefined"
          />
        </template>
        <template #fallback> Loading... </template>
      </suspense>
    </keep-alive>
  </transition>
</router-view>

在路径组件上使用转场,并对导航进行动画处理

单个路由过度
const routes = [
  {
    path: '/custom-transition',
    component: PanelLeft,
    meta: { transition: 'slide-left' },
  },
  {
    path: '/other-transition',
    component: PanelRight,
    meta: { transition: 'slide-right' },
  },
]
<router-view v-slot="{ Component, route }">
  <!-- 使用任何自定义过渡和回退到 `fade` -->
  <transition :name="route.meta.transition || 'fade'">
    <component :is="Component" />
  </transition>
</router-view>
强制在复用的视图之间进行过渡

Vue 可能会自动复用看起来相似的组件,从而忽略了任何过渡。幸运的是,可以添加key属性来强制过渡。这也允许你在相同路由上使用不同的参数触发过渡:

<router-view v-slot="{ Component, route }">
  <transition name="fade">
    <component :is="Component" :key="route.path" />
  </transition>
</router-view>
keep-alive

vue中的keep-alive的用法详细讲解 - 知乎 (zhihu.com)

  • 所以使用keep-alive就是保持组件活跃,不会被destroy销毁掉,就一直还活着,组件没有被销毁掉的话,组件上挂载的数据就还存在,所以状态就可以保留,所以,keep-alive就可以保持组件的状态。
<!-- 使用keep-alive包了一层,就可以缓存啦 -->
<keep-alive>
    <router-view></router-view>
</keep-alive>

include属性

include 包含的意思。值为字符串或正则表达式或数组。只有组件的名称与include的值相同的才会被缓存,即指定哪些被缓存,可以指定多个被缓存。这里以字符串为例,指定多个组件缓存,语法是用逗号隔开。如下:

// 指定home组件和about组件被缓存
<keep-alive include="home,about" >
    <router-view></router-view>
</keep-alive>

exclude属性

exclude相当于include的反义词,就是除了的意思,指定哪些组件不被缓存,用法和include类似,如下:

// 除了home组件和about组件别的都缓存,本例中就是只缓存detail组件
<keep-alive exclude="home,about" >
    <router-view></router-view>
</keep-alive>
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值