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

方案二:使用 beforeRouteUpdate

或者,使用 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可以看到背景图和分类的数据查询出来了

image-20240709102823264

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

image-20240709102850515

相关推荐

  1. vue3参数动态

    2024-07-11 05:30:07       40 阅读
  2. vue3页面缓存一种方法

    2024-07-11 05:30:07       33 阅读
  3. vue3 + ts,如何获取传递参数

    2024-07-11 05:30:07       36 阅读

最近更新

  1. docker php8.1+nginx base 镜像 dockerfile 配置

    2024-07-11 05:30:07       53 阅读
  2. Could not load dynamic library ‘cudart64_100.dll‘

    2024-07-11 05:30:07       55 阅读
  3. 在Django里面运行非项目文件

    2024-07-11 05:30:07       46 阅读
  4. Python语言-面向对象

    2024-07-11 05:30:07       56 阅读

热门阅读

  1. 【seo常见的问题】搜索引擎

    2024-07-11 05:30:07       22 阅读
  2. D1.排序

    D1.排序

    2024-07-11 05:30:07      20 阅读
  3. Leetcode 1143. Longest Common Subsequence

    2024-07-11 05:30:07       22 阅读
  4. 从像素角度出发使用OpenCV检测图像是否为彩色

    2024-07-11 05:30:07       25 阅读
  5. ES索引模板

    2024-07-11 05:30:07       17 阅读
  6. ”极大似然估计“和”贝叶斯估计“思想对比

    2024-07-11 05:30:07       20 阅读
  7. 理解Gunicorn:Python WSGI服务器的基石

    2024-07-11 05:30:07       21 阅读