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基于session和github-oauth2实现登录注册验证思路详解

    vue基于session和github-oauth2实现登录注册验证思路详解

    通过 sessionId 可以在 session 表中获取用户的信息,此外,还利用 session 表实现了GitHub 的 OAuth2 第三方登录,本文讲解前端通过简单的方式实现一个基本的登录注册验证功能,感兴趣的朋友跟随小编一起看看吧
    2024-08-08
  • 登录页面的实现及跳转代码实例(vue-router)

    登录页面的实现及跳转代码实例(vue-router)

    在Vue.js中可以使用vue-router来实现前端路由,通过路由来跳转页面,这篇文章主要给大家介绍了关于登录页面的实现及跳转(vue-router)的相关资料,需要的朋友可以参考下
    2023-12-12
  • Vue中qs插件的使用详解

    Vue中qs插件的使用详解

    这篇文章主要介绍了Vue中qs插件的使用详解,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习学习吧
    2020-02-02
  • 解决vue addRoutes不生效问题

    解决vue addRoutes不生效问题

    这篇文章主要介绍了解决vue addRoutes不生效问题,具有很好的参考价值,希望对大家有所帮助。一起跟随小编过来看看吧
    2020-08-08
  • 一文秒懂Vue3的v-model

    一文秒懂Vue3的v-model

    v-model 是 Vue 内置的指令作为属性接收一个变量(不能是常量)绑定到普通组件和自定义组件中,本文给大家介绍Vue3的v-model示例代码,感兴趣的朋友跟随小编一起看看吧
    2023-02-02
  • Vue中emit事件无法触发的问题及解决

    Vue中emit事件无法触发的问题及解决

    这篇文章主要介绍了Vue中emit事件无法触发的问题及解决方案,具有很好的参考价值,希望对大家有所帮助。如有错误或未考虑完全的地方,望不吝赐教
    2022-09-09
  • Vue中使用js-cookie详情

    Vue中使用js-cookie详情

    这篇文章主要介绍了Vue中使用js-cookie详情,文章围绕js-cookie的相关资料展开详细内容具有一定的的参考价值,需要的小伙伴可以参考一下
    2022-03-03
  • Vue3打包部署报错的解决方案

    Vue3打包部署报错的解决方案

    这篇文章主要介绍了Vue3打包部署报错的解决方案,具有很好的参考价值,希望对大家有所帮助。如有错误或未考虑完全的地方,望不吝赐教
    2022-06-06
  • Vue实现一个动态添加行的表格步骤详解

    Vue实现一个动态添加行的表格步骤详解

    在Vue组件中定义表格的数据模型,通常使用一个数组来存储表格的数据,每一行数据可以是一个对象,对象的属性对应表格的列,这篇文章主要介绍了Vue实现一个动态添加行的表格步骤详解,需要的朋友可以参考下
    2024-05-05
  • Vue使用.sync 实现父子组件的双向绑定数据问题

    Vue使用.sync 实现父子组件的双向绑定数据问题

    这篇文章主要介绍了Vue使用.sync 实现父子组件的双向绑定数据,需要的朋友可以参考下
    2019-04-04

最新评论