WhatsApp网页版登录WhatsApp网页版登录

WhatsApp中文版

浏览器回退按钮事件_History API 数据刷新

上一世,我没搞懂History API 与数据刷新WhatsApp网页版,被面试官拷打,被周天辉大人训斥。(没能让周天辉大人尽兴真是抱歉);

这一世,我携这篇博客霸气归来,势必要拿回属于我的一切!!!

History API 数据刷新 _ 单页应用路由变化监听 _浏览器回退按钮事件

原生的History API 1. history.back()

popstate 是浏览器历史记录变化时触发的事件,常用于单页应用(SPA)中监听路由变化。

​2. history.forward()​3. history.go(n) ​灵活性:可一次性跳转多步WhatsApp网页版,比 back() 和 forward() 更灵活。​触发事件:同 back() 和 forward()。​4. history.pushState(state, title, url) ​示例:

history.pushState({ page: 1 }, "Page 1", "/page1");

​5. history.replaceState(state, title, url) ​示例:

history.replaceState({ page: 2 }, "Page 2", "/page2");

​6. window.location 方法 ​location.replace(url): ​关键区别总结方法/属性是否重新加载页面修改历史堆栈触发事件典型场景

history.back()

移动指针

popstate

用户手动后退

history.forward()

移动指针

popstate

用户手动前进

history.go(n)

移动指针

popstate

跳转多步历史记录

history.pushState()

新增条目

无(需手动触发)

SPA 动态更新 URL

history.replaceState()

替换当前条目

无(需手动触发)

修改当前历史记录(如重定向)

location.href

新增条目

页面加载事件

传统页面跳转

location.replace()

替换当前条目

页面加载事件

重定向且不保留当前历史

​事件关联 ​hashchange 事件: ​使用建议​单页应用(SPA)​:优先使用 pushState() 和 replaceState() 管理路由。​导航操作:用 back()、forward()、go() 代替手动修改 location.href。​兼容性:pushState() 和 replaceState() 不支持 IE9 及以下WhatsApp网页版,需提供降级方案(如哈希路由)。手撕实现​一、核心原理​历史堆栈:维护一个数组存储历史记录(包含状态、URL 等信息)。​指针控制:通过指针(currentIndex)跟踪当前位置。​事件触发:自定义事件(如 popstate)通知状态变化。​二、代码实现

class CustomHistory {
  constructor() {
    this.stack = [];       // 历史记录堆栈
    this.currentIndex = -1; // 当前指针位置
    this.state = null;     // 当前状态
    this.events = {};      // 事件监听器
  }
  // 添加事件监听
  on(event, callback) {
    this.events[event] = callback;
  }
  // 触发事件
  trigger(event, state) {
    if (this.events[event]) {
      this.events[event]({ state });
    }
  }
  // 模拟 pushState
  pushState(state, title, url) {
    // 生成新记录(忽略 title,仅保留 state 和 url)
    const newRecord = { state: JSON.parse(JSON.stringify(state)), url };
    // 清除当前指针后的记录(模拟浏览器行为)
    this.stack = this.stack.slice(0, this.currentIndex + 1);
    this.stack.push(newRecord);
    this.currentIndex = this.stack.length - 1;
    this.state = state;
    // 不触发 popstate 事件
  }
  // 模拟 replaceState
  replaceState(state, title, url) {
    if (this.currentIndex === -1) return;
    const newRecord = { state: JSON.parse(JSON.stringify(state)), url };
    this.stack[this.currentIndex] = newRecord;
    this.state = state;
  }
  // 模拟 back()
  back() {
    if (this.currentIndex > 0) {
      this.currentIndex--;
      this.state = this.stack[this.currentIndex].state;
      this.trigger('popstate', this.state);
    }
  }
  // 模拟 forward()
  forward() {
    if (this.currentIndex < this.stack.length - 1) {
      this.currentIndex++;
      this.state = this.stack[this.currentIndex].state;
      this.trigger('popstate', this.state);
    }
  }
  // 模拟 go(n)
  go(n) {
    const targetIndex = this.currentIndex + n;
    if (targetIndex >= 0 && targetIndex < this.stack.length) {
      this.currentIndex = targetIndex;
      this.state = this.stack[this.currentIndex].state;
      this.trigger('popstate', this.state);
    }
  }
}

​三、使用示例

const myHistory = new CustomHistory();
// 监听 popstate 事件
myHistory.on('popstate', (event) => {
  console.log('State changed:', event.state);
});
// 添加历史记录
myHistory.pushState({ page: 1 }, '', '/page1');
myHistory.pushState({ page: 2 }, '', '/page2');
// 后退
myHistory.back(); // 触发 popstate,state 变为 { page: 1 }
// 前进
myHistory.forward(); // 触发 popstate,state 变为 { page: 2 }
// 替换当前记录
myHistory.replaceState({ page: 3 }, '', '/page3');
// 跳转两步(此处无效,因为堆栈长度不足)
myHistory.go(-2);

​四、与原生的区别特性原生 History API自定义实现

​依赖浏览器行为

是(如页面加载、安全性限制)

完全手动控制

​URL 自动更新

需手动处理(如修改地址栏)

​popstate 触发时机

仅 back()/forward()/go()

可自定义(如 pushState 时)

​安全性限制

受同源策略限制

无限制

​五、扩展方向​URL 同步:结合 window.location.hash 或 history.pushState 实现地址栏同步。​持久化存储:将堆栈保存到 localStorage 以实现页面刷新后恢复。​路由拦截:添加钩子函数(如 beforeNavigate)控制导航行为。​SPA 集成:配合前端框架(React/Vue)实现路由跳转和组件渲染。什么会导致API接口刷新一、用户主动行为

​页面刷新(F5 / 浏览器刷新按钮)​

强制重新加载页面,触发所有初始化 API 请求(如页面加载时的 useEffect、componentDidMount)。

​表单提交(Submit)​

提交表单时通常会向 API 发送 POST/PUT 请求,更新数据并可能触发后续 GET 请求。

​手动点击按钮/链接

例如“搜索”按钮触发 fetch(),或导航菜单跳转路由时调用 API。​二、前端隐式行为

​前端路由变化

单页应用(SPA)中切换路由时,可能自动调用 API(如 React Router 的 useParams 监听变化)。

​状态变化触发副作用

如 React 中 useState 变化导致 useEffect 重新执行并调用 API:

const [userId, setUserId] = useState(1);
useEffect(() => {
  fetch(`/api/user/${userId}`); // userId 变化时刷新 API
}, [userId]);

3.​定时轮询(Polling)​通过 setInterval 定期调用 API 更新数据:

setInterval(() => {
  fetch('/api/data'); // 每 5 秒刷新一次
}, 5000);

4.​WebSocket 或 Server-Sent Events (SSE)

服务端推送新数据通知后,前端主动请求最新数据。

​三、浏览器/网络行为

​离线恢复在线

浏览器从离线状态恢复时,可能自动重试失败的 API 请求。

​缓存失效

当 API 响应缓存过期(如 Cache-Control: max-age=60),浏览器重新发起请求。

​导航历史操作

通过 history.back() 或前进后退按钮返回到页面时,若前端监听 popstate 并主动调用 API:

window.addEventListener('popstate', () => {
  fetch('/api/data'); // 后退/前进时刷新
});

​四、后端触发行为

​Webhook 回调

​Token 过期

​五、代码主动调用

​显式调用请求函数

// 手动触发 API 刷新
const reloadData = () => {
  fetch('/api/data');
};

​框架内置方法

如 Vue 的 vm.$forceUpdate() 可能间接触发 API 调用(若与响应式数据绑定)。

​六、避免过度刷新的优化策略

限制高频操作(如搜索框输入)的 API 请求次数。

使用 localStorage 或内存缓存避免重复请求相同数据。

通过 If-Modified-Since 或 ETag 让服务端决定是否返回新数据。

提供“暂停更新”按钮供用户选择是否停止轮询。

History API 数据刷新 _浏览器回退按钮事件_ 单页应用路由变化监听

“ 那些我曾对你承诺的所以,隐藏在黑夜中把我吞没”

相关文章