Vue3动态路由(响应式带参数的路由)变更页面不刷新的问题解决办法

 更新时间:2024年07月12日 09:55:04   作者:笑小枫  
问题来源是因为我的开源项目Maple-Boot项目的网站前端,因为项目主打的内容发布展示,所以其中的内容列表页会根据不同的菜单进行渲染不同的路由,本文降介绍Vue3动态路由变更页面不刷新的问题解决办法,需要的朋友可以参考下

背景

先说说问题,问题来源是因为我的开源项目Maple-Boot项目的网站前端,因为项目主打的内容发布展示,所以其中的内容列表页会根据不同的菜单进行渲染不同的路由。

这里路由path使用的是/blog/:menu?,通过menu的参数来渲染对应的内容,但是遇到了一个问题,在使用<RouterLink :to="{name: blog, params: {menu:java}}">跳转时,改变params的值,页面不会重新渲染。

    {
      path: "/blog/:menu?",
      name: "blog",
      component: BlogView,
    },

官方答疑

查看官网,得到结论如下:

官网地址:https://router.vuejs.org/zh/guide/essentials/dynamic-matching.html

使用带有参数的路由时需要注意的是,当用户从 /users/johnny 导航到 /users/jolyne 时,相同的组件实例将被重复使用。因为两个路由都渲染同个组件,比起销毁再创建,复用则显得更加高效。不过,这也意味着组件的生命周期钩子不会被调用

同时也给出了解决方案

方案一:使用watch

要对同一个组件中参数的变化做出响应的话,你可以简单地 watch $route 对象上的任意属性,在这个场景中,就是 $route.params

方案二:使用 beforeRouteUpdat​​​​​​​

或者,使用 beforeRouteUpdate 导航守卫,它还允许你取消导航

我的解决方案

我复用的页面是BlogView,原始完整内容如下,主要看不同的内容,防止直接贴部分代码有同学找不到头脑,这里贴全部的内容吧,很多引用是找不到的

<script setup>
import {onMounted, reactive, watch} from "vue";
import { useRoute } from 'vue-router';

import Meta from "@/examples/Meta.vue";
import DefaultNavbar from "@/examples/navbars/NavbarDefault.vue";
import Header from "@/examples/Header.vue";
import DefaultFooter from "@/examples/footers/FooterDefault.vue";
import BlogIndex from "./Sections/BlogIndex.vue";


import {getWebMenuByPath} from "../../api/common";

const route = useRoute();

const state = reactive({
  webMenuInfo: {},
  isGetData: false
});

onMounted(() => {
  getWebMenuByPathClick(route.params.menu);
});

const getWebMenuByPathClick = (menuPath) => {
  getWebMenuByPath(menuPath).then(res => {
    state.webMenuInfo = res;
    state.isGetData = true;
  });
}

</script>
<template>
  <Meta v-if="state.isGetData" :webMenuInfo="state.webMenuInfo"/>
  <div class="container position-sticky z-index-sticky top-0  opacity-8">
    <div class="row">
      <div class="col-12">
        <DefaultNavbar :sticky="true"/>
      </div>
    </div>
  </div>
  <Header>
    <div
      class="page-header min-height-400"
      :style="{ backgroundImage: `url(${state.webMenuInfo.image})` }"
      loading="lazy"
    >
      <span class="mask bg-gradient-dark opacity-3"></span>
    </div>
  </Header>
  <BlogIndex :menuPath="state.webMenuInfo.path"/>
  <DefaultFooter />
</template>

修改后的内容

<script setup>
import {onMounted, reactive, watch} from "vue";
import { useRoute } from 'vue-router';

import Meta from "@/examples/Meta.vue";
import DefaultNavbar from "@/examples/navbars/NavbarDefault.vue";
import Header from "@/examples/Header.vue";
import DefaultFooter from "@/examples/footers/FooterDefault.vue";
import BlogIndex from "./Sections/BlogIndex.vue";


import {getWebMenuByPath} from "../../api/common";

const route = useRoute();

const state = reactive({
  webMenuInfo: {},
  isGetData: false
});

onMounted(() => {
  getWebMenuByPathClick(route.params.menu);
});

const getWebMenuByPathClick = (menuPath) => {
  getWebMenuByPath(menuPath).then(res => {
    state.webMenuInfo = res;
    state.isGetData = true;
  });
}

watch(() => route.params.menu, (newId, oldId) => {
  getWebMenuByPathClick(route.params.menu);
})

</script>
<template>
  <Meta v-if="state.isGetData" :webMenuInfo="state.webMenuInfo"/>
  <div class="container position-sticky z-index-sticky top-0  opacity-8">
    <div class="row">
      <div class="col-12">
        <DefaultNavbar :sticky="true"/>
      </div>
    </div>
  </div>
  <Header>
    <div
      class="page-header min-height-400"
      :style="{ backgroundImage: `url(${state.webMenuInfo.image})` }"
      loading="lazy"
    >
      <span class="mask bg-gradient-dark opacity-3"></span>
    </div>
  </Header>
  <BlogIndex :menuPath="state.webMenuInfo.path" :key="state.webMenuInfo.path"/>
  <DefaultFooter />
</template>

变更点一:变更的点主要是加了watch监听route.params变化时,重新请求数据。

watch(() => route.params.menu, (newId, oldId) => {
  getWebMenuByPathClick(route.params.menu);
})

变更点二:在<BlogIndex>子组件上添加:key="state.webMenuInfo.path",通过不同的key标注为不同组件

<BlogIndex :menuPath="state.webMenuInfo.path" :key="state.webMenuInfo.path"/>

看下效果

通过路由/blog/article可以看到背景图和分类的数据查询出来了

当路由切换到/blog/nterview-fenbushi,可以看到背景图发生了变化,同时因为没有配置对应的分类栏目,数据渲染为空的。

到此这篇关于Vue3动态路由(响应式带参数的路由)变更页面不刷新的问题解决办法的文章就介绍到这了,更多相关Vue3动态路由变更页面不刷新内容请搜索脚本之家以前的文章或继续浏览下面的相关文章希望大家以后多多支持脚本之家!

相关文章

  • Vue中$bus的用法及$on、$off的使用说明

    Vue中$bus的用法及$on、$off的使用说明

    这篇文章主要介绍了Vue中$bus的用法及$on、$off的使用说明,具有很好的参考价值,希望对大家有所帮助。如有错误或未考虑完全的地方,望不吝赐教
    2022-05-05
  • webpack dev-server代理websocket问题

    webpack dev-server代理websocket问题

    这篇文章主要介绍了webpack dev-server代理websocket问题,具有很好的参考价值,希望对大家有所帮助,如有错误或未考虑完全的地方,望不吝赐教
    2024-08-08
  • Vue3使用el-form嵌套el-table进行单条数据的表单校验功能

    Vue3使用el-form嵌套el-table进行单条数据的表单校验功能

    在实际开发过程中,我们经常需要处理表格中的表单数据,比如在编辑表格中的某一行数据时进行校验,本文给大家介绍了Vue3使用el-form嵌套el-table进行单条数据的表单校验功能,文中有相关的代码供大家参考,需要的朋友可以参考下
    2024-08-08
  • vue项目中页面跳转传参的方法总结

    vue项目中页面跳转传参的方法总结

    在Vue项目中,你可以使用路由(vue-router)来实现页面跳转并传递参数,这篇文章主要为大家整理了一些常用的方法,感兴趣的小伙伴可以学习一下
    2023-11-11
  • 解决vue-cli脚手架打包后vendor文件过大的问题

    解决vue-cli脚手架打包后vendor文件过大的问题

    今天小编就为大家分享一篇解决vue-cli脚手架打包后vendor文件过大的问题。具有很好的参考价值,希望对大家有所帮助。一起跟随小编过来看看吧
    2018-09-09
  • 利用vue3+ts实现管理后台(增删改查)

    利用vue3+ts实现管理后台(增删改查)

    这篇文章主要介绍了利用vue3+ts实现管理后台(增删改查),文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习学习吧
    2020-10-10
  • Vue3使用setup监听props实现方法详解

    Vue3使用setup监听props实现方法详解

    这篇文章主要为大家介绍了Vue3使用setup监听props实现方法详解,有需要的朋友可以借鉴参考下,希望能够有所帮助,祝大家多多进步,早日升职加薪
    2023-08-08
  • vue axios拦截器常用之重复请求取消

    vue axios拦截器常用之重复请求取消

    我们大家在开发中,经常会遇到接口重复请求导致的各种问题,下面这篇文章主要给大家介绍了关于axios拦截器之重复请求取消的相关资料,需要的朋友可以参考下
    2021-09-09
  • axios封装与传参示例详解

    axios封装与传参示例详解

    这篇文章主要给大家介绍了关于axios封装与传参的相关资料,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习学习吧
    2020-10-10
  • Vue如何用this.$set改变数组里的某个值

    Vue如何用this.$set改变数组里的某个值

    这篇文章主要介绍了Vue用this.$set改变数组里的某个值,文中通过示例代码介绍了vue中this.$set()的用法----更新数组和对象的值,需要的朋友可以参考下
    2022-12-12

最新评论