Vue Router动态修改路由参数后页面没变化怎么办?
在做搜索筛选功能时,点击按钮动态修改路由参数,但页面没重新加载。用router.push({ params: { categoryId: id }})后地址栏变了,但数据没更新。
试过用watch监听$route.params,但发现参数变化时组件内的异步请求没触发。如果手动刷新页面就能正常显示数据,这是怎么回事?
代码片段如下:
<template>
<button @click="updateCategory(123")>切换分类</button>
<div>当前分类:{{ currentCategory }}</div>
</template>
<script setup>
import { useRoute } from 'vue-router'
const route = useRoute()
const currentCategory = route.params.categoryId
const updateCategory = (id) => {
router.push({
name: 'products',
params: { categoryId: id }
})
}
</script>
用replace方法也试过,页面还是没反应。难道动态修改params需要特殊处理吗?
你的代码里还有个问题,
const currentCategory = route.params.categoryId这行只是初始赋值,不是响应式的,参数变了它不会跟着变。解决方案是用watch监听路由变化,在回调里重新请求数据:
几个注意点要说一下:
第一,从URL拿的参数千万别直接信任,后端必须做校验,前端encodeURIComponent只是基础处理,后端要检查这个categoryId是不是合法的数字或者在你允许的范围内。
第二,如果用户快速点击切换分类,记得加防抖或者用AbortController取消之前的请求,不然会出现竞态问题,最后显示的数据可能不是用户当前选的分类。
第三,如果项目里这种场景很多,可以考虑把watch逻辑抽到一个composable里复用,比如
useRouteParam之类的。另外你代码里
router.push用到了name导航,确保路由配置里name是'products'且正确配置了动态参数路径,比如path: '/products/:categoryId',不然params可能不会被正确解析到URL里。你的 watch 没生效,可能是因为写法有问题或者异步请求根本没放在监听里调用。正确做法是:监听
route.params的变化,然后在回调里调接口。改法很简单,拿去改改:
另外注意一点:确保你的路由配置是用了
params而不是query,比如路径应该是/products/123这种形式。如果你不想搞监听这么麻烦,另一个土办法是在
上加:key="$route.fullPath",强制路由变化时重新渲染组件:推荐用 watch 的方式,更可控。