一、背景
在 JavaScript 中,如果你想在不刷新页面的情况下设置 URL 参数(查询字符串),你可以使用 history.pushState 或 history.replaceState 方法来修改浏览器历史记录和当前 URL。这两种方法都允许你更改 URL 而不会重新加载页面。
二、JavaScript 使用 history.pushState 方法
history.pushState 方法用于在浏览器历史记录中添加一个新的状态。当你点击浏览器的后退或前进按钮时,可以返回到这个状态。
测试成功
// 假设当前 URL 是 http://example.com/page // 新的 URL 参数
const newParams = { foo: 'bar', baz: 'qux' };
const queryString = new URLSearchParams(newParams).toString(); // 新的 URL
const newUrl = window.location.pathname + '?' + queryString; // 将新的状态(可以是任何对象)和新的 URL 添加到历史记录中
// 第三个参数是可选的标题,目前大多数浏览器都忽略它
history.pushState({ page: 1 }, '', newUrl); // 现在 URL 已经更新为 http://example.com/page?foo=bar&baz=qux
二、JavaScript 使用 history.replaceState方法
history.replaceState 方法用于修改当前的历史记录条目,而不是添加一个新的条目。这意味着用户不能通过浏览器的后退按钮回到之前的 URL。
测试成功
// 假设当前 URL 是 http://example.com/page // 新的 URL 参数
const newParams = { foo: 'bar', baz: 'qux' };
const queryString = new URLSearchParams(newParams).toString(); // 新的 URL
// const newUrl = window.location.pathname + '?' + queryString;
const newUrl = window.location.href+ '?' + queryString; // 替换当前的历史记录条目和 URL
// 第一个参数是新的状态(可以是任何对象),第二个参数是可选的标题,第三个参数是新的 URL
history.replaceState({ page: 1 }, '', newUrl); // 现在 URL 已经更新为 http://example.com/page?foo=bar&baz=qux
// 但之前的 URL(例如 http://example.com/page)不能通过后退按钮访问
三、解析和读取新的 URL 参数
为了读取 URL 参数,你可以使用 URLSearchParams 对象
// 获取当前 URL 的查询字符串部分
const queryString = window.location.search.substring(1); // 去掉开头的 '?'
const params = new URLSearchParams(queryString); // 读取参数
const foo = params.get('foo'); // 'bar'
const baz = params.get('baz'); // 'qux' console.log(foo, baz);
四、注意事项
使用 history.pushState 或 history.replaceState 后,如果你希望用户能够通过点击浏览器的后退按钮来恢复之前的状态,你需要在 popstate 事件中处理这个逻辑
window.addEventListener('popstate', (event) => { console.log('location: ', document.location, 'state: ', event.state); // 在这里处理状态变化
});
在单页面应用(SPA)中,这种方法非常有用,因为它允许你在不重新加载页面的情况下动态地更新 URL 和应用状态。
五、Vue中的处理
在 Vue.js 应用中,特别是当你使用 Vue Router 时,你可以通过编程方式改变路由参数而不需要刷新页面。Vue Router 提供了多种方法来实现这一点,包括 router.push 和 router.replace。
5.1、使用 router.push
router.push 方法用于导航到一个不同的 URL,这个操作会将新路由添加到历史记录中,因此用户可以点击浏览器的后退按钮回到之前的页面。
// 假设你有一个路由配置如下
// { path: '/user/:id', component: User } // 在 Vue 组件中
this.$router.push({ name: 'user', params: { id: 123 } });
// 或者使用路径和查询参数
// this.$router.push({ path: '/user/123', query: { foo: 'bar' } }); // 如果目标是同一个路由,但是查询参数或散列值要改变,你可能需要使用 `query` 对象
// 注意,`params` 是用于动态路由匹配的,而 `query` 是用于查询字符串的
this.$router.push({ query: { page: 2 } });
// 如果想要替换当前页面而不是添加新页面到历史记录,可以使用 `replace: true`
// this.$router.push({ query: { page: 2 } }, { replace: true });
5.2、使用 router.replace
router.replace 方法与 router.push 类似,但它不会向历史记录中添加新条目,而是替换当前的条目。这意味着用户不能使用浏览器的后退按钮回到之前的页面。
this.$router.replace({ name: 'user', params: { id: 123 } });
5.3、vue中监听路由变化
// 在一个Vue组件中
watch: { '$route.params.id'(newVal, oldVal) { // 路由参数中的 id 发生变化时执行的逻辑 console.log('ID changed from', oldVal, 'to', newVal); }
}
5.4、注意事项
当你使用 params 时,你通常是在匹配一个动态路由。确保你的路由配置中有对应的动态部分。
使用 query 时,你是在添加查询字符串参数到 URL。这些参数不会改变路由的路径部分,但会作为查询字符串附加在 URL 后面。
当你改变路由参数时,Vue Router 会自动更新 <router-view> 中渲染的组件,而不需要重新加载整个页面。
如果你想在 URL 改变时执行一些额外的逻辑(例如,获取新的数据),你可以在路由的 beforeEnter 守卫或组件内的 beforeRouteUpdate 守卫中处理这些逻辑。
通过 Vue Router 的这些功能,你可以在不刷新页面的情况下动态地改变路由参数,并在 Vue 应用中提供流畅的导航体验。