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动态路由变更页面不刷新内容请搜索脚本之家以前的文章或继续浏览下面的相关文章希望大家以后多多支持脚本之家!