去他的history.go(-N)和pushState popstate,改用replaceState完美解决

本文探讨了在前端应用中,如何正确使用HTML5 History API的replaceState方法来管理页面跳转和返回逻辑,以实现从表单页返回列表页的需求,避免了因pushState增加历史记录条目而导致的混乱。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

都是返回上一页闹得,打球都心不在焉了。
除了首页,其他的页面左上角都有一个返回上一页的按钮。这样的功能合情合理。一个window.history.go(-1)就能搞定的玩意儿。

新需求来了,如下:

需求一:
A页:列表页(不同的业务,不同的列表页)
B页:详细页(同一个详细页)
C页:表单页(同一个表单页)

A—>B—>C(提交成功)—>B(点击返回上一页)—>A

需求二:

客户端(浏览器、微信、APP)的回退按钮也需要同样的功能

解决方案(自以为是):

window.history.go(-3):本来欣喜,这么简单就搞定了,实践证明这是个错误

(1)页面见的跳转是通过A标签href或者window.location.href,这会在历史记录history中增加一条历史条目,A—>B—>C—>B—>A,go(-3)可以满足需求一。
(2)使用history.pushState()函数,popstate事件配合,事件处理程序中调用需求一的函数,想当然就这么觉得完成了。
(3)自测一下,全乱了都是哪里到哪里,迷路了,再也回不去了。
(4)就钻了-1…-N的牛角尖无法自拔了,埋头揉了一顿头发,发型已乱,现在是晚上10点,喊个滴滴回家。
(5)周末熄灯睡不着了,问问老伴儿有没有好的想法,还真有,由于此功能放到了公用模块了,pushState会在history中增加一条历史条目,导致不需要这个返回逻辑的页面,在go(-1)时出现了混乱。一个后端从逻辑给个行的同的建议还是,晚安好梦。
(6)周一,到了单位,迫不及待试一下,凌乱了。popstate想要触发,想这种情景下使用history.pushState()是最合适的,可是它会增加记录,只能这样乱着,虽然我属于总在放弃治疗边缘不断试探的人,可总归是试探,绝不玩真格儿的。电脑给面子,此时蓝屏了,哈哈哈哈,我已疯。

解决方案(靠谱点的):

-1…-N是控制不了了,MDN上的pushState、replaceState、popstate,看了N遍,榆木脑壳,没开窍,网上也有对比pushState、replaceState区别的,一个增加一条历史条目,一个把当前的替换掉,不增加。现在的情况就是增加一条导致的,如果没有pushState作妖儿,不就可以了吗,用replaceState试试吧。

(1)A—>B:replaceState(‘replaceurl’,null,‘B页面地址’);
(2)B—>C:replaceState(‘replaceurl’,null,‘C页面地址’);
(3)C—>B:replaceState(‘replaceurl’,null,‘B页面地址’);

这时候无论点击B页左上角的返回上一页,还是客户端的回退按钮,老老实实回到了来时的A列表页,这个由于replaceState指将当前历史条目进行替换,不会增加新历史条目。只在页面左上角返回按钮加事件处理程序go(-1)即可,客户端的回退按钮不用理。

当然也可以使用window.href.replace()实现。

混沌了三天,终于尘埃落定。万物必有其存在的道理,html5给出replaceState就是干这个的。

反省:
1:pushState、replaceState、popstate相关原理理解不透彻,误用乱用。
2:对需求只盯表象,不究本质。

如果有好建议,欢迎聊聊!!

<think>好的,我现在需要回答用户的问题:“使用 history.pushState() replaceState() 是否会影响 history.go() 的效果?” 首先,我要回顾用户之前的对话。用户之前询问了关于javascript:history.go(-1)的问题,现在接着问关于pushStatereplaceState是否影响history.go()的效果。这个问题属于浏览器历史记录管理的范畴,需要深入理解HTML5 History API的相关方法。 首先,我需要确认history.pushState()replaceState()的作用。这两个方法是HTML5引入的,允许开发者在不重新加载页面的情况下修改浏览器的历史记录。pushState()会向历史记录栈中添加一个新的状态,而replaceState()则是替换当前的历史记录条目。这常用于单页应用(SPA)中,以实现无刷新页面导航。 接下来,用户想知道这两个方法是否会影响history.go()的效果。history.go()用于在历史记录中导航,参数是正数或负数,表示前进或后退的步数。比如history.go(-1)相当于后退一步。 接下来需要分析这两者的关系。当使用pushStatereplaceState修改历史记录后,历史记录栈的结构会发生变化。例如,添加新的条目会增加历史记录的长度,替换条目则不会改变长度但会改变当前条目。因此,调用history.go()时,其导航的路径会受到这些修改的影响。 需要明确的是,虽然pushStatereplaceState修改了历史记录栈,但它们并不会触发页面的重新加载,这是传统导航的不同之处。然而,当用户使用history.go()导航到被这些方法修改过的条目时,浏览器会根据当前的历史记录栈进行跳转,但不会重新加载页面,除非条目中包含实际的页面加载(比如通过传统导航跳转的页面)。 另外,需要注意的是,使用pushStatereplaceState时,虽然改变了URL,但页面的内容不会自动更新,这需要开发者通过监听popstate事件来手动处理内容的变化。当用户使用history.go()导航到由这些方法创建的历史条目时,会触发popstate事件,开发者可以在此事件中更新页面内容。 此外,pushStatereplaceState可以添加或修改state对象,这个对象可以在popstate事件中被获取,用于恢复页面状态。因此,在SPA中,这些方法结合popstate事件处理,可以实现复杂的前端路由管理。 总结来说,pushStatereplaceState会修改浏览器的历史记录栈,从而影响history.go()的行为,但实际的页面导航需要开发者配合popstate事件处理来实现内容的更新,而不会自动加载新页面。因此,回答用户的问题时,需要明确说明这种影响,并指出在SPA中的典型应用方式。 在回答时,还要注意用户可能存在的后续问题,比如如何结合这些方法实现路由管理,或者安全性问题,但当前问题仅关注对history.go()的影响,需保持回答的针对性。 需要确保回答结构清晰,分点说明影响,并给出示例,如使用pushState添加条目后,history.go(-1)的行为变化。同时,提醒用户注意popstate事件的处理,以正确更新页面内容。 最后,检查是否存在可能的误解,例如认为pushState会导致页面重新加载,需要明确说明它们不会触发页面加载,但会改变历史记录栈,从而影响history.go()的导航路径。</think>**是的,`history.pushState()` `replaceState()` 会影响 `history.go()` 的效果**,因为它们直接操作浏览器的历史记录栈。以下是具体影响的说明: --- ### 1. **`pushState()` 的作用** - **功能**:向历史记录栈**添加新条目**,但不会触发页面加载或刷新。 - **对 `history.go()` 的影响**: - 新增的条目会成为历史记录的一部分,例如: ```javascript // 当前栈:[A](当前页) history.pushState({}, "", "/pageB"); // 栈变为:[A, B] history.go(-1); // 返回 A(因为栈中有 A → B) ``` - 如果多次调用 `pushState()`,历史栈长度增加,`history.go(-N)` 可以回退更多步骤。 --- ### 2. **`replaceState()` 的作用** - **功能**:**替换当前历史记录条目**,不增加栈长度。 - **对 `history.go()` 的影响**: - 当前条目被覆盖,但栈长度不变,例如: ```javascript // 原始栈:[A] history.replaceState({}, "", "/newA"); // 栈仍为:[A],但 A 的内容被替换为 newA history.go(-1); // 无法回退(因为栈长度未变,当前已是栈顶) ``` --- ### 3. **关键特性** - **不触发 `popstate` 事件**:调用 `pushState()` 或 `replaceState()` 时,**不会触发** `popstate` 事件。只有用户手动操作(如点击后退按钮)或调用 `history.go()`、`back()`、`forward()` 时才会触发。 - **`state` 对象传递**:可以通过 `pushState()` 的 `state` 参数存储数据,后续在 `popstate` 事件中通过 `event.state` 读取: ```javascript history.pushState({ page: "settings" }, "", "/settings"); window.addEventListener("popstate", (event) => { console.log(event.state); // 输出 { page: "settings" } }); ``` --- ### 4. **实际应用场景** - **单页应用(SPA)路由**:Vue Router、React Router 等框架通过 `pushState` `replaceState` 实现无刷新页面切换。例如: ```javascript // Vue Router 内部逻辑简化 function navigate(path) { history.pushState({}, "", path); updateViewBasedOnPath(); // 手动更新页面内容 } ``` - **表单提交后保留状态**:提交表单后,用 `replaceState` 替换当前 URL,避免用户重复提交。 --- ### 5. **注意事项** - **安全性限制**:出于隐私保护,**无法通过 JavaScript 直接读取完整历史记录**,只能操作当前标签页的栈。 - **路径需同源**:`pushState` `replaceState` 的 URL 必须与当前页面同源(Same-origin)。 --- ### 总结 - **会改变历史栈**:`pushState()` 增加条目,`replaceState()` 修改当前条目,均影响 `history.go()` 的导航范围。 - **需配合 `popstate` 事件**:开发者需监听此事件,手动更新页面内容,否则 URL 变化但页面不刷新。
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值