vue3不能使用history.pushState修改url参数踩坑
马格纳斯 人气:0前言
在重构我的 vue-use-sync-url(辅助将数据和 url 参数进行同步的工具库)时,遇到了一个使用 window.history.pushState
来修改地址栏的 url 参数的 bug,准确来说是 vue-router
的 bug,下面就来讲讲具体是怎么回事。
问题
场景如下,有一个输入框里面输入了内容,点击搜索按钮使用 window.history.pushState
将数据同步到 url 参数上。然后再点击 go about
按钮跳转到别的页面,关键的来了,这时候你点击浏览器左上角的回退按钮回到刚才的页面,url 上的 keywords
参数变没了! 这里上个测试链接 codesandbox
<script setup> import { ref } from "vue"; const keywords = ref("123") const handleClick = () => { window.history.pushState({}, "", `${window.location.pathname}?keywords=${keywords.value}`) } </script> <template> <input v-model="keywords" /> <button @click="handleClick">搜索</button> <router-link to="/about">go about</router-link> </template>
追根溯源
一开始想是不是我写的有问题?测试了 vue2-router
和 react-router
都没有这个问题,所以我就将问题锁定在了 vue3-router
了。因为 router-link
和直接执行了 router.push
操作是一样的,所以我就去找 push
操作所在的源码位置,最终在 packages/router/src/history/html5.ts
中找到了如下代码。
可以看到在这个 push
函数中,在第 288 行,执行了一次 replace
的操作,而在第 297 行才是真正的 push
操作。我将第 288 行注释之后,上面的 demo 就跑通了,但是直觉告诉我它这里这么做是有原因的,但是想弄明白估计得将整个库的源码看完,没有这个精力。直接提了个 issue,在它的 github issue 中我发现了好几个由于这个第 288 行代码产生的问题,例如 #1416、#1526、#1529。维护者在我的 issue 中是这么回答的。
结合他在其它 issue 中的回答,大概是如下这么个意思。直接使用 history
api,路由器是不知道的,应该避免使用,最好使用 router.push
来进行更改。还说到第 288 行对于更新当前历史记录条目是必要的,以便能够通过导航守卫取消ui 发起的导航。它允许知道导航的方向和在历史堆栈中的相对位置。不幸的是,目前还没有其他方法可以做到这一点。
我补充道,在 vue2
和 react
中没有这个问题,你不觉得这是个 bug
吗?他说在 vue2
中使用 hisotry
api 可能会产生你没有遇到过的问题,vue-router
在 vue3
中比 vue2
拥有更多的功能等等。
解决
没办法,维护者不觉得这是个 bug,最后只能妥协使用 router.push
来解决,并将 vue-router
的依赖添加到 peerDependencies
中。在一些场景下,如果想封装一个库在各个框架中共同使用就不行了,在这里必须使用 router.push
才可以,我觉得还是不太好的。
加载全部内容