原生andriod浏览器回退后dom(click)事件全体失效问题探究
问题描述
今天同事遇到一个神一样的BUG:
在原生浏览器下,为dom元素绑定一个click事件,其中有个a标签外链,点击a后进入其他页面,点击浏览器后退后,页面点击事件全体失效!
我于是用ios测了下没事,用andriod其他浏览器试了下也没事,就是原生的有问题,怀疑是特定的手机有问题,又陆续换了几台,发现原生的都有问题
于是便开始找解决方案,下面就来聊下今天的漫长之路,这里先给会出问题的代码:
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8" />
<title></title>
<meta name="viewport" content="width=device-width, initial-scale=1.0, minimum-scale=1.0, maximum-scale=1.0, user-scalable=no">
</head>
<body>
<div id="ttt">
ttt</div>
<br />
<a href="http://www.baidu.com" name="n">百度一下</a>
<script type="text/javascript">
var i = 0;
var appendDiv = function (msg) {
var div = document.createElement('div');
if (msg) {
div.innerHTML = msg;
} else {
div.innerHTML = i++;
}
document.body.appendChild(div);
};
document.addEventListener('click', function (e) {
appendDiv('click')
});
</script>
</body>
</html>
DOM事件丢失
第一步想到的当然是事件丢失了,或者就是不执行了,于是乎写了一段代码:
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8" />
<title></title>
<meta name="viewport" content="width=device-width, initial-scale=1.0, minimum-scale=1.0, maximum-scale=1.0, user-scalable=no">
</head>
<body>
<div id="ttt">
ttt</div>
<br />
<a href="http://www.baidu.com" name="n">百度一下</a> dsfsdffd<br>
<script type="text/javascript">
var i = 0; setInterval(function () {
var div = document.createElement('div');
div.innerHTML = i++;
document.body.appendChild(div); var type = 'click'; //要触发的事件类型
var event = document.createEvent('MouseEvents');
event.initMouseEvent(type);
document.dispatchEvent(event); }, 1000);
var appendDiv = function (msg) {
var div = document.createElement('div');
if (msg) {
div.innerHTML = msg;
} else {
div.innerHTML = i++;
}
document.body.appendChild(div);
};
document.addEventListener('click', function (e) {
appendDiv('click')
});
</script>
</body>
</html>
我定时器不停地向浏览器打印数字,而且触发document的click事件,他工作的蛮好的,但是当我点击百度一下再回来时候,便不执行了
因为我们没法在代码层面上获取dom的事件信息,所以暂时只能这样做,而我的判断是,没错!dom事件丢失了
Window事件未丢失
然后我又在这上面纠缠了好久,想试试windows的事件是否丢失,于是写下了以下代码:
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8" />
<title></title>
<meta name="viewport" content="width=device-width, initial-scale=1.0, minimum-scale=1.0, maximum-scale=1.0, user-scalable=no">
</head>
<body>
<div id="ttt">
ttt</div>
<br />
<a href="http://www.baidu.com" name="n">百度一下</a> dsfsdffd<br>
<script type="text/javascript">
var i = 0; setInterval(function () {
var div = document.createElement('div');
div.innerHTML = i++;
document.body.appendChild(div); var type = 'click'; //要触发的事件类型
var event = document.createEvent('MouseEvents');
event.initMouseEvent(type);
document.dispatchEvent(event); }, 1000);
var appendDiv = function (msg) {
var div = document.createElement('div');
if (msg) {
div.innerHTML = msg;
} else {
div.innerHTML = i++;
}
document.body.appendChild(div);
};
document.addEventListener('click', function (e) {
appendDiv('click')
}); window.onresize = function () {
appendDiv('onresize')
}
</script>
</body>
</html>
我点击回来后,发现事件还在,于是陷入深深的沉思.沉思.沉思.思.思.思.............
问题解决
最后我无意间将这个问题解决了,而且解决的方案匪夷所思:
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8" />
<title></title>
<meta name="viewport" content="width=device-width, initial-scale=1.0, minimum-scale=1.0, maximum-scale=1.0, user-scalable=no">
</head>
<body>
<div id="ttt">
ttt</div>
<br />
<a href="http://www.baidu.com" name="n">百度一下</a> dsfsdffd<br>
<script type="text/javascript">
var t = document.getElementById('ttt');
var i = 0;
setInterval(function () {
var div = document.createElement('div');
div.innerHTML = i++;
document.body.appendChild(div);
}, 1000);
var appendDiv = function (msg) {
var div = document.createElement('div');
if (msg) {
div.innerHTML = msg;
} else {
div.innerHTML = i++;
}
document.body.appendChild(div);
};
document.addEventListener('click', function (e) {
appendDiv('click')
});
</script>
</body>
</html>
整个解决方案耗费我两个多小时,而最终却是这么一段不起眼的代码:
var t = document.getElementById('ttt');
// var btnfree = document.getElementsByTagName('a'); 无效
// var n = document.getElementsByName('name');无效
现在问题是解决了,我却更疑惑了,一个大大的问号在我脑里回旋不去,尼玛在玩我啊......这是为什么??????
问题原理猜想
注意,此处完全是扯淡时间
andriod硬件加速
andriod原生浏览器本身使用了硬件加速功能,或者说andriod对自身的浏览器做了很好的处理
我们在页面上看到的页面具有一个dom树,而我们的事件js保存在另一个地方,而此时硬件加速为我们提供了一个类似png的中间件
他负责了通讯,但是在我们该网页转入后台时,这之间的映射关系却被破坏了
而我们js代码中若是多了这么一段代码:
var t = document.getElementById('ttt');
他的映射关系又建立起来了,如果是这样的话,是说的过去的!!!
PS:以上的理论显然无法说服我
垃圾回收/后台挂起
不得已的情况下,我想到了js的垃圾回收,dom结构活生生的在页面上,页面不会回收,里面的i一直在用也不会回收
但是我们的DOM树好像并没有神引用在页面中保存,因为没有浏览器就正好将所有的事件全部销毁了。
而后面我们在js中保存了一个dom树,他就没有销毁????
PS:这里我可以将t给delete了试试,但是我在家没有环境,只得明天再试了,今天暂时到这里
问题追踪
var t = document.getElementById('ttt');
t = null;
最后这样加一句,问题又会复现,所以垃圾回收的概率较高。
结语
当然,这是andriod浏览器本身一个BUG,但是如果我们可以从这种小BUG中发现大问题,或者原理性的东西,那真的该好好的研究一番了!!!
若是您有任何想法,请不吝赐教!!!
原生andriod浏览器回退后dom(click)事件全体失效问题探究的更多相关文章
- 关于IOS下click事件委托失效的解决方案
一.由于某些特殊情况下,需要用到事件委托,比如给动态创建的DOM绑定click事件,这里就需要事件委托(这里就牵扯到:目标元素和代理元素)目标元素:动态创建的元素,最终click事件需要绑定到该元素 ...
- 手机浏览器下IScroll中click事件
产品的h5页面几乎都使用了iscroll插件,如果a标签在iscroll里,在部分手机浏览器中会出现无法点击的情况,不管是绑定click事件还是使用a标签的href属性.href属性偶尔还会能点击,c ...
- JQuery实现click事件绑定与触发方法分析
原生JS通过什么方法绑定click事件? 原生js有一下三种方法为DOM对象绑定click事件, 第一种,在html中添加 onclick属性,在此属性中添加要绑定的事件函数,如下, 这种方法为htm ...
- 如何解决 touchstart 事件与 click 事件的冲突
一 · 业务场景的描述 在对已完成的PC站点进行移动端适配时,我们想要站点在移动设备上有更快的响应速度,以带给用户更好的体验,此时,我们应该使用移动设备专用的事件系统,例如,使用 touchstart ...
- IOS的Safari浏览器中,点击事件失效的原理及解决办法
这里做了事件委托,简单区分一下[目标元素]和[代理元素],为后续论述理解做铺垫. [目标元素]:实际希望点击的元素,可以是任意标签. [代理元素]:代替[目标元素]触发点击事件的元素,有可能是目标元素 ...
- IOS下的 click 点击失效
当委托给一个元素添加click事件时,如果事件是委托到 document 或 body 上,并且委托的元素是默认不可点击的(如 div, span 等),此时 click 事件会失效. demo: & ...
- safari浏览器click事件要点击两次才有响应出现闪烁
闪烁问题 由于在iOS Safari上click事件存在300ms响应延时,所以为touch事件添加样式,会和click事件默认样式叠加而产生闪烁问题. 因为ios safari浏览器中对触摸事件的响 ...
- 苹果浏览器移动端click事件延迟300ms的原因以及解决办法
这要追溯至 2007 年初.苹果公司在发布首款 iPhone 前夕,遇到一个问题 —— 当时的网站都是为大屏幕设备所设计的.于是苹果的工程师们做了一些约定,应对 iPhone 这种小屏幕浏览桌面端站点 ...
- 关于IOS浏览器:document,body的click事件触发规则
今天做了个手机页面,点击某个按钮->弹出菜单,再点击菜单以外的任意位置->关闭菜单,在其他浏览器里面没有问题,但是在IOS浏览器中并不会关闭. 网上解决这个bug的帖子很多,这篇帖子主要是 ...
随机推荐
- 错误:document.getElementById("userForm").submit();Object is not a function
表单提交时发生的错误解决办法: 利用这种方法进行表单提交的时候,表单中的元素不能有 name="submit"的元素,否则该元素会与submit()方法造成混淆,导致错误!
- Anliven - 解决问题的一些方法
How to resolve the problem? 获取基本的相关信息(后续处理问题的基础) 在怎样的背景环境下?发生了怎样的问题? 如果无法清楚地辨别或陈述问题的基本信息,那么,此时要面对的将 ...
- 可视化工具gephi源码探秘(一)
今天在老大和小梁的鼓舞和忽悠下(^_^),我决定还是把之前下载好的gephi源码好好利用起来,不在朝三暮四的想d3js或是什么vizster,用心去选择一个自己熟悉的,而不是一直在各种困难之间来回徘徊 ...
- 3种Java从文件路径中获取文件名的方法
package test; import java.io.File; public class FileName { /** * @param args */ public static void m ...
- 关于MVC中模型model的验证问题
今天在做项目练习的时候发现,MVC中使用自带的模型验证时会提前显示在界面上,比如下面所示: 这是什么原因了,是因为我在表示get请求的action里面返回了其界面所显示使用的model,我们知道mvc ...
- win10 服务(系统默认服务)注册表
---恢复内容开始--- Windows Registry Editor Version 5.00 [HKEY_LOCAL_MACHINE\SYSTEM\ControlSet001\Services] ...
- MySQL 快速导入大量数据 资料收集
一.LOAD DATA INFILE http://dev.mysql.com/doc/refman/5.5/en/load-data.html 二. 当数据量较大时,如上百万甚至上千万记录时,向My ...
- ASP.NET Core WebAPI 开发-新建WebAPI项目
ASP.NET Core WebAPI 开发-新建WebAPI项目, ASP.NET Core 1.0 RC2 即将发布,我们现在来学习一下 ASP.NET Core WebAPI开发. 网上已经有泄 ...
- C# POST Https请求的一些坑
写在前面: 从上次,跟合作方的站点对接开始就产生了这个问题,当时用C#进行POST提交,总是会出现问题,找了很久发现对方的站点居然是TLS 1.2 的. 正文: 然而,在.NET FrameWork ...
- Nofuser - deobfuscator for Confuser
google搜索了好久,最终找到这个工具,可直接使用. 虽然脱后有很多无用代码,但关键代码是还是很清晰的! ----------------------------NoFuser----------- ...