移动端h5监听浏览器返回操作(目前在react项目中用到)

栏目: 服务器 · 发布时间: 6年前

内容简介:1、利用2、利用

前言

1.主要是返回是默认的浏览器返回事件是返回上一个页面。

2.处理页面各种弹窗,点击物理返回应该隐藏这些弹窗而不是直接返回页面。

3.总结下问题,h5应该希望能监听到返回事件并且做一些处理。

相关知识

1、利用 popstate 事件,点击浏览器前进,后退会触发popstate事件。

2、利用 hashchange 事件,页面hash改变是会触发此事件(适合react,vue单页面应用)。

一、window.onpopstate

每当处于激活状态的历史记录条目发生变化时,popstate 事件就会在 对应window 对象上触发. 如果当前 处于激活状态的历史记录条目是由history.pushState() 方法创建,或者由 history.replaceState()方法修改过 的, 则 popstate事件对象的state 属性包含了这个历史记录条目的state对象的一个拷贝.

调用 history.pushState() 或者 history.replaceState() 不会触发popstate事件. popstate 事件只会在浏览器某些行为下触发, 比如点击后退、前进按钮(或者在JavaScript中调用 history.back()、history.forward()、history.go() 方法).

history.pushState() 不会刷新页面,往历史记录中添加一条记录。

history.replaceState() 不会刷新页面,替换当前页面记录,不会在历史记录中新增。

兼容性:当网页加载时,各浏览器对 popstate 事件是否触发有不同的表现,Chrome 和 Safari会触发 popstate 事件, 而Firefox不会.

可参考相关文档

假如当前网页地址为 example.com/example.htm… ,则运行下述代码后:

window.onpopstate = () => {} 等同于 window.addEventListener('popstate',() => {});
​
window.onpopstate = function(event) {
  alert("location: " + document.location + ", state: " + JSON.stringify(event.state));
};
//绑定事件处理函数. 
history.pushState({page: 1}, "title 1", "?page=1");    //添加并激活一个历史记录条目 http://example.com/example.html?page=1,条目索引为1   当前记录有两条记录(包括最开始的)
history.pushState({page: 2}, "title 2", "?page=2");    //添加并激活一个历史记录条目 http://example.com/example.html?page=2,条目索引为2   当前记录有三条记录
history.replaceState({page: 3}, "title 3", "?page=3"); //修改当前激活的历史记录条目 http://ex..?page=2 变为 http://ex..?page=3,条目索引为3  当前记录有三条(replaceState会替换第三条条)
history.back(); // 弹出 "location: http://example.com/example.html?page=1, state: {"page":1}"
history.back(); // 弹出 "location: http://example.com/example.html, state: null
history.go(2);  // 弹出 "location: http://example.com/example.html?page=3, state: {"page":3}
​复制代码

移动端h5监听浏览器返回操作(目前在react项目中用到)

如上图,假设当前页面是A页面,跳转到B页面,B页面打开dialong弹窗,这个时候点击返回,默认是返回到A页面。这种体验是很差的,优化体验,这个时候需要优化这种体验性能问题。

场景:在B页面中有个弹窗,点击返回,要关闭弹窗,再次点击,返回到A页面。

代码如下:

// 假设A页面为http://www.example.com/a.html 
// B页面是http://www.example.com/b.html 
// 下面以react生命周期为例
componentDidMount: function() {
    window.addEventListener('popstate',(state) => {
        // 监听到返回事件,注意,只有触发了返回才会执行这个方法
        console.log(state);
        this.back();
    })
}
// 假设点击打开对话窗,利用pushState添加一天记录
openDialong: function() {
    // 此时页面地址为b.html?page=1,但是页面没有刷新。并且不会触发popstate方法
    history.pushState({page: 1}, "title 1", "?page=1");
    // TODO
    
}
// 弹窗已存在,并且点击了返回事件,此时页面b.html?page=1--->b.html,并触发popstate事件
back: function() {
    // 页面在用户看来是没有刷新的,此时是关闭dialong
    // TODO
    
}
// 离开页面的时候取消监听popstate
componentWillUnmount: function() {
    window.removeEventListener('popstate',(state) => {
        this.back();
    }) 
}复制代码

二、window.onhashchange

当 一个窗口的 hash (URL 中 # 后面的部分)改变时就会触发 hashchange 事件(参见 location.hash )。

if ("onhashchange" in window) {
    alert("该浏览器支持 hashchange 事件!");
}
​
function locationHashChanged() {
    if (location.hash === "#somecoolfeature") {
        somecoolfeature();
    }
}
​
window.onhashchange = locationHashChanged;复制代码

还是以上面场景为例:

// 假设A页面为http://www.example.com/a.html#/a 
// B页面是http://www.example.com/a.html#/b 
// 下面以react生命周期为例
componentDidMount: function() {
    window.addEventListener('hashchange',(state) => {
        // hash改变就会触发
        const href = location.href;
        // 当前hash中不存在?page=1是触发(初始化刚进来是不会触发这个方法的)
        if (href.indexOf('?page=1') < 0) {
          this.back();
        }
    })
}
// 假设点击打开对话窗,利用pushState添加一天记录
openDialong: function() {
    // 此时页面地址为a.html?page=1,但是页面没有刷新。并且不会触发popstate方法
    // history.pushState({page: 1}, "title 1", "?page=1");
    // 不过此时会触发hashchange,但是加个判断;
    this.props.history.push('/b?page=1'); 
    // TODO
    
}
// 弹窗已存在,并且点击了返回事件,此时页面a.html?page=1--->a.html,并触发hashchange事件
back: function() {
    // 页面在用户看来是没有刷新的,此时是关闭dialong
    // TODO
    
}
// 离开页面的时候取消监听hashchange
componentWillUnmount: function() {
    window.removeEventListener('hashchange',(state) => {
        this.back();
    }) 
}
​复制代码

三、优化**

移动端h5监听浏览器返回操作(目前在react项目中用到)

还是这个图片

假设A是首页,B详情页面,C是支付页面,D是结果页面。(我们希望D不能返回到C页面)。

假设要从D页面跳转到B页面(B,C,D也一样), 从结果页面D中点击按钮跳转到详情B页面,可再次购买。

有以下方法:

方法一:location.href = 'http://www.example/b.html';
方法二:history.go(-2);复制代码

主要区别:

方法一会往历史记录中添加新的记录,变成A—>B—>C—>D—>B。

此时点击物理返回,就会回到D页面。而这不是我们要的结果。

方法二是回到历史记录中,不会新增记录,链路还是A—>B—>C—>D。

D页面不应该回到C页面

此时我们就可以用到上面的方法,点击返回利用history.go()的方法,回到我们想到的页面。

// D页面---->B页面
componentDidMount: function() {
    this.props.history.push('/b?page=1'); 
    // 如果有问题,加个setTimeout
    window.addEventListener('hashchange',(state) => {
        // hash改变就会触发
        const href = location.href;
        // 当前hash中不存在?page=1是触发(初始化刚进来是不会触发这个方法的)
        if (href.indexOf('?page=1') < 0) {
          this.back();
        }
    })
}
// 并且点击了返回事件,此时页面d.html?page=1--->d.html,并触发hashchange事件
back: function() {
    // 页面在用户看来是没有刷新的,此时是回到B页面
    // TODO
    this.props.history.go(-2);
}
// 离开页面的时候取消监听hashchange
componentWillUnmount: function() {
    window.removeEventListener('hashchange',(state) => {
        this.back();
    }) 
}复制代码

兼容性可查看

有问题欢迎指正。


以上就是本文的全部内容,希望本文的内容对大家的学习或者工作能带来一定的帮助,也希望大家多多支持 码农网

查看所有标签

猜你喜欢:

本站部分资源来源于网络,本站转载出于传递更多信息之目的,版权归原作者或者来源机构所有,如转载稿涉及版权问题,请联系我们

深入理解计算机系统(原书第2版)

深入理解计算机系统(原书第2版)

(美)Randal E.Bryant、David O'Hallaron / 龚奕利、雷迎春 / 机械工业出版社 / 2011-1-1 / 99.00元

本书从程序员的视角详细阐述计算机系统的本质概念,并展示这些概念如何实实在在地影响应用程序的正确性、性能和实用性。全书共12章,主要内容包括信息的表示和处理、程序的机器级表示、处理器体系结构、优化程序性能、存储器层次结构、链接、异常控制流、虚拟存储器、系统级I/O、网络编程、并发编程等。书中提供大量的例子和练习,并给出部分答案,有助于读者加深对正文所述概念和知识的理解。 本书的最大优点是为程序......一起来看看 《深入理解计算机系统(原书第2版)》 这本书的介绍吧!

JSON 在线解析
JSON 在线解析

在线 JSON 格式化工具

HTML 编码/解码
HTML 编码/解码

HTML 编码/解码

Base64 编码/解码
Base64 编码/解码

Base64 编码/解码