• vue-router的核心概念


    一,两种路由模式

    1.1 hash模式(对应HashHistory)

    特点:

    • 页面监听#号后面的url变化,这种路由模式所有的变化都在前端执行不会像服务器发送请求
    • 每次hash值变化都会在浏览器的访问历史中增加一个记录。
    • hash不会造成404的问题,因为所有的解析都在前端完成

    1.2 history模式(对应HTML5History)

    特点:

    • 是HTML5新推出的功能,比hash url更美观,在浏览器刷新页面时,会真实按照路径发送请求
    • 如果发送请求的路径nginx没有匹配到,就会出现404页面
    • 改变url:history提供了pushStatereplaceState两种方法来记录路由状态,这两种方法只会改变url,不会刷新页面
    • 监听url变化:通过onpopstate事件监听history的变化,在点击浏览器的前进或者后退时触发,根据状态信息加载对应的页面内容。

    二,router-link

    router-link组件的本质就是a标签,他绑定了click事件,然后通过执行对应的VueRouter实例的push()实现的。他使Vue Router可以在不重新加载页面的情况下更改URL,处理URL的生成以及编码。

    使用示例:

    1. "{ name: 'detail', params: { appId: '12345' }}">
    2. this.$router.push({ name: 'detail', params: { appId: '12345' }})

    二者实现效果一致

    三,router-view

    router-view组件是一个函数式组件(没有data,没有组件实例),他的主要作用就是路由变化时渲染指定url的组件。他可以放在任何地方,来适应项目中的布局。

    使用示例:

    支持使用name进行命名

    1. class="left" name="left">
    2. <router-view class="home">router-view>
    3. routes: [
    4. {
    5. path: '/',
    6. components: {
    7. default: Home,
    8. // left: left的缩写。与 `` 上的 `name` 属性匹配
    9. left,
    10. },
    11. },
    12. ],

    四,$route

    概念:当前路由信息的对象。获取和当前路由相关的信息,route是只读的属性,可以通过watch来监听路由的变化。

    常用属性:

    • fullPath: ""  // 当前路由完整路径(包含查询参数和hash)
    • hash: "" // 当前路由的 hash 值 (锚点)
    • meta: {} // 路由文件中自赋值的meta信息
    • name: "" // 当前路由名称
    • path: ""  // 当前路由路径
    • params: {}  // 包含了动态片段和全匹配片段就是一个空对象。
    • query: {}  // 表示 URL 查询参数。跟随在路径后用'?'带的参数

    五,$router

    概念:vueRouter的实例对象。他是一个全局路由对象,可以通过this.$router访问路由或路由提供的方法。

    常用属性/方法:

    • router.push - 路由跳转
    • router.replace - 替换当前路由页面(这样跳转不会产生历史记录)
    • router.go - 跳转到具体某个历史记录
    • router.back - 历史记录向回退
    • router.forward - 历史记录向前进
    • router.hasRoute() - 判断路由是否存在
    • router.getRoutes() - 获取所有路由组成的数组
    • router.addRoute($options) - 添加路由
    • router.removeRoute($name) - 删除路由
    • router.beforeEach((to, from, next) - 全局路由前置守卫
    • router.beforeResolve((to, from, next)  - 全局路由解析守卫
    • router.afterEach((to, from) - 全局路由后置守卫
    • ... ...

    六,路由守卫

    6.1 全局守卫

    • router.beforeEach(to, from, next)- 全局前置守卫。在路由跳转前触发类似于拦截器,主要用来做登陆验证
    • router.afterEach(to, from)- 全局后置守卫。在路由跳转完成后触发(因此没有next
    • router.beforeResolve(to, from, next)- 全局解析守卫。每次导航都会触发,他是在所有组件内守卫beforeEach和组件内beforeRouteEnter之后、afterEach之前调用。可以用来获取数据和执行操作等。

    6.2 独享路由守卫

    理解:直接在路由配置上定义,但是它只在进入路由时触发不会在 params、query 或 hash 改变时触发

    示例:

    1. const routes = [
    2. {
    3. path: '/detail/:id',
    4. component: appDetail,
    5. // 直接在路由配置中定义守卫
    6. beforeEnter: (to, from, next) => {
    7. next()
    8. },
    9. },
    10. ]

    beforeEnter可以接受一个函数数组,用于路由守卫重用,例如:

    1. const routes = [
    2. {
    3. path: '/detail/:id',
    4. component: appDetail,
    5. beforeEnter: [removeQueryParams, removeHash],
    6. }
    7. ]
    8. // 守卫函数1
    9. function removeQueryParams(to) {
    10. if (Object.keys(to.query).length)
    11. return { path: to.path, query: {}, hash: to.hash }
    12. }
    13. // 守卫函数2
    14. function removeHash(to) {
    15. if (to.hash) return { path: to.path, query: to.query, hash: '' }
    16. }

    6.3 组件内的守卫

    概念:组件内的路由守卫就像组件各个生命周期的钩子函数。

    • beforeRouteEnter(to,from, next) -- 进入之前。在渲染该组件的对应路由被验证前调用此时组件实例还没有被创建,不能访问this
    • beforeRouteUpdate(to,from, next) -- 路由变化时。在当前路由改变,但是该组件被复用时调用(触发这个的时候,组件已经挂载好了,可以访问this
    • beforeRouteLeave(to,from, next) -- 离开后。在导航离开渲染该组件的对应路由时调用(可以访问this

    6.4 路由守卫触发顺序

    页面加载时

    1,全局前置守卫 - beforeEach

    2,A组件独享守卫 - beforeEnter

    3,A组件路由守卫 - beforeRouteEnter

    4,全局解析守卫 - beforeResolve

    5,全局后置守卫 - afterEach

    [6,组件的挂载:beforeCreate => created => beforeMount]

    7,A组件路由守卫 beforeRouteEnter 中的 next回调(此时能够获取到组件实例 vm

    [8,A组件完成挂载:mounted]

    点击切换路由时

    1,A组件守卫 - beforeRouteLeave

    2,全局前置守卫 - beforeEach

    [3,在重用的组件里调用 beforeRouteUpdate ]

    4,B组件独享守卫 - beforeEnter

    5,B组件路由守卫 - beforeRouteEnter

    6,全局解析守卫 - beforeResolve

    7,全局后置守卫 - afterEach

    [8,B组件挂载:beforeMount]

    9,B组件路由守卫 beforeRouteEnter 中的 next回调

    10,A组件beforeDestory

    11,A组件destory

    12,[B组件完成挂载mounted]

    路由更新时

    触发beforeRouteUpdate

    七,异步获取数据

    异步调用接口获取数据,通常有两种情况:

    1,在导航完成之后调用接口(通过created或mounted

    2,在导航完成之前调用接口,然后调用导航的next(vm => vm.setData())(通过beforeRouteEnter

    示例:

    1. // 导航完成之后
    2. created() {
    3. const id = this.$route.params.id; // 从路由获取参数
    4. getList().then((response) => {
    5. if (response.code === 10000) {
    6. // ...
    7. }
    8. })
    9. },
    10. // 导航完成之前
    11. beforeRouteEnter(to, from, next) {
    12. const id = to.params.id; // 从路由参数获取参数
    13. getList(id, (err, post) => { // 成功的回调
    14. next(vm => vm.setData(err, post)); // next方法接受的vm参数调setData传数据
    15. })
    16. },

    八,滚动scrollBehavior

    概念vue-router支持页面滚动效果实现,仅需提供一个scrollBehavior方法即可(在创建VueRoute对象时)。

    使用方式scrollBehavior(to, from, savedPosition) { return 期望滚动到的位置 }

    注意

    • 返回falsy空对象则不滚动。
    • savedPosition是在按下浏览器的前进、后退按钮时触发,返回一个位置对象

    示例

    1. const router = createRouter({
    2. history: createWebHashHistory(),
    3. routes: [...],
    4. scrollBehavior (to, from, savedPosition) {
    5. // 方式1:指定位置信息。滚动到顶部
    6. return { top: 0 };
    7. // 方式2:相对指定CSS选择器的偏移位置
    8. return { el: "#main", top: 10 };
    9. // 方式3:相对指定DOM元素的偏移位置
    10. let dom = document.getElementById('main');
    11. return { el: dom, left: 10 };
    12. // 方式4:滚动到锚点
    13. if (to.hash) {
    14. return { el: to.hash };
    15. }
    16. // 方式5:延迟滚动 - 返回一个promise对象,在resolve中传参位置信息
    17. return new Promise((resolve, reject) => {
    18. setTimeout(() => {
    19. resolve({ top: 10, left: 20});
    20. }, 500)
    21. })
    22. }
    23. })
    1. const router = createRouter({
    2. scrollBehavior(to, from, savedPosition) {
    3. if (savedPosition) {
    4. return savedPosition
    5. } else {
    6. return { top: 0 }
    7. }
    8. },
    9. })

    九,keep-alive

    概念:keep-alive是vue的一个内置组件,主要作用是缓存组件在内存中,防止重复渲染dom。

    常用属性

    • include - 字符串或正则。匹配到的name会被缓存
    • exclude - 字符串或正则。匹配到的name不会被缓存
    • max - 数字。最多可以缓存多少个组件实例

    路由搭配应用

    可以在路由的元信息meta中设置keepAlive属性,来判断是否需要缓存,例如:

    1. {
    2. path: 'list',
    3. name: 'itemList',
    4. component: () => import '@/pages/item/list',
    5. meta: {
    6. keepAlive: true, // 保存当前路由是否需要缓存
    7. title: '列表页'
    8. }
    9. }
    10. <keep-alive>
    11. <router-view v-if="$route.meta.keepAlive">router-view>
    12. keep-alive>
    13. <router-view v-if="!$route.meta.keepAlive">router-view>

    删除keep-alive中的缓存:

    1,首先对router-view标签设置ref属性(例如:<router-view ref="routerView">router-view>)

    2,通过delete删除ref.$vnode.parent.componentInstance.cache属性(例如:

    delete this.$refs.routerView.$vnode.parent.componentInstance.cache)

  • 相关阅读:
    python之面向对象编程
    web练习
    C#基础总结三
    线下商家卖货难、拓客难、引流难,不如学习一下怎么结合O2O电商
    Python面向对象总结一
    OpenCV中的边缘检测技术及实现
    统计字符出现次数类Counter
    MySQL之数据查询(WHERE)
    漏洞预警|CVE-2023-38545 Curl 和 libcurl 堆缓冲区溢出漏洞
    typedef和#define的花里胡哨的用法
  • 原文地址:https://blog.csdn.net/wjs0406/article/details/133377920