事因

网站中的遮罩层大都有一个问题,就是在这个遮罩层中滑动,里面的内容也会跟着滑动,我是这样想的,既然都有这个问题,干脆写一个通用的插件出来,省的每个还得单独处理。如果是单独处理这个问题是比较好解决的,关键问题是,我想写的这个插件是,你直接在有问题的页面中引入这个插件就行,而不需要做其他的任何事情,而难就难在这,因为我们不知道什么时候需要阻止滑动,什么时候是正常滑动。

灵感

下班后的路上在想,虽然我们不知道是哪段代码引起的,但如果我们能够分析出什么时候会发生这件事,那就解决了一半的问题,而什么时候会发生我们是可以知道的,在问出这个问题的时候就可以知道,既然是因为在弹出层中滑动引起的,那么也就是说在滚动的时候会发生这件事。而我的想法就是在滚动事件中加一个判断,如果是正常滚动那么就不做任何处理,而如果是由其他DOM冒泡导致里面的内容发生滚动的,那么就不让它滚动。

也就是类似下面这段代码

window.addEventListener("scroll",function(event){
if(非正常滚动){
.....
}
});

实践

那么我们怎么知道它是不是正常滚动,一开始我想的是获取event对象中的target属性,之所以我想获取这个属性是因为它能够确定当前正在活动的DOM,而如果我们能够知道当前活动的DOM是什么,也就可以用它来判断是不是非正常滚动,因为如果body是活动状态,那么就属于正常滚动了,而如果是其他的那么就属于非正常滚动。但遗憾的是,不管是在遮罩层中引发的滚动还是直接在body中滚动,event.target获取到的都是body,也就是说此路不通。

虽然说直接用event.target失败了,但我想一定有能够获取到当前活动的DOM,虽然以前没用过,也没听说过,于是我就将event打印出来,看看它里面都有哪些属性,注意是打印两次,一次是正常滚动的数据,一次是非正常滚动的数据,把它们对比一下。不看不知道,一对比还真发现了点什么,event.target中有一个activeElement属性,而这个正是我苦苦寻找的,从名字上看也能够看出点什么,“活动元素”,怪我无知,还以为自己javascript学的有多好,竟然这个属性都没用过。

有了这个发现以后,我们的代码就变成下面这样啦

window.addEventListener("scroll",function(event){
if(event.target.activeElement.tagName.toLowerCase()!=="body"){
解决bug代码
}
});

解决bug倒也简单,直接给html或者body添加一个overflow:hidden;就ok了,代码如下

window.addEventListener("scroll",function(event){
if(event.target.activeElement.tagName.toLowerCase()!=="body"){
document.all[0].style.overflow= "hidden";
}
});

我这里是给html添加的,防止代码被其他同事窜改,因为body比较多人操作。

虽然上面已经解决了很大一部分问题,但还有一个问题得解决,那就是当遮罩层被关闭我们应该去掉html的overflow:hidden;不然文档超出的部分就看不见了。而我们现在需要解决的问题就是,怎么知道遮罩层被关闭?

分析了一下,所有的遮罩层基本上都是通过点击事件来关闭的,也就是说我们可以通过监听点击事件来去掉html的overflow:hidden;不过直接用click事件会有些问题,有时不会被触发,我这里用的是touchend事件,至于为什么不用touchstart也是有原因的,等等再说,现在我们的代码变成了下面这样

document.addEventListener("touchend",function(){
document.all[0].style.overflow= "auto";
}); window.addEventListener("scroll",function(event){
if(event.target.activeElement.tagName.toLowerCase()!=="body"){
document.all[0].style.overflow= "hidden";
}
});

运行以上代码,我们很快发现了一个新问题,它会出现一卡一卡的,仔细分析,发现直接在touchend事件中改变html的overflow是有问题的,因为不是所有情况都是属于关闭遮罩层的,有可能是在里面正常的滚动,而滚动就需要我们点击一下遮罩层,前面也就是因为忽略了这件事导致卡顿现象的,你想象一下,一下取消一下又不取消,这不是纠结吗。

所以我们还得想另外一个办法,我想到的是,判断一下是属于点击事件,还是滑动事件,至于怎么区分的话,我用了一个计数器,但这个计数器大于2的话就属于滑动事件,代码如下

var count = 0;

document.addEventListener("touchmove",function(){
count++;
}); document.addEventListener("touchend",function(){
if(count<2){
document.all[0].style.overflow= "auto";
}
count = 0;
}); window.addEventListener("scroll",function(event){
if(event.target.activeElement.tagName.toLowerCase()!=="body"){
document.all[0].style.overflow= "hidden";
}
});

到此就结束啦,还有一件事没说,那就是之所以使用touchend事件而没有使用touchstart事件,是因为touchstart在touchmove后不会执行,因此会造成count有时没有被清零。

虽然这个插件确实可以用,但还是有一点点的问题没办法解决,自己测试一下就明白了。

总结

这一次还是蛮有挑战的,倒不是说有多难,关键是要学会把问题看清,把问题分析清楚。要解决的问题是什么?已知什么?通过已知的可以解决什么问题?这也是本次实践的收获吧。

记一次解决CSS定位bug思路的更多相关文章

  1. 记一次解决layui 的bug - layer.open 与 layui渲染问题

    场景是这样的,通过layer打开一个弹窗,里面放置一个表单,表单是用layui来渲染的. 当弹窗完成之后,我需要渲染表单中的一些内容.譬如laydate. layer.open({ type: 1, ...

  2. (高德地图)marker定位 bug 解决总结

    项目背景: 一个项目bug,项目中用到高德地图,默认打开页面会生成一个marker(下图红色icon),然后用户拖动marker到想要的位置,并且保存. 用户反映定位不准确,在当前页面编辑的位置,到后 ...

  3. 【Unity游戏开发】记一次解决 LuaFunction has been disposed 的bug的过程

    一.引子 RT,本篇博客记录的是马三的一次解决 LuaFunction has been disposed 的bug的全过程,事情还要从马三的自研框架 ColaFrameWork 说起.最近,马三在业 ...

  4. vue—你必须知道的 js数据类型 前端学习 CSS 居中 事件委托和this 让js调试更简单—console AMD && CMD 模式识别课程笔记(一) web攻击 web安全之XSS JSONP && CORS css 定位 react小结

    vue—你必须知道的   目录 更多总结 猛戳这里 属性与方法 语法 计算属性 特殊属性 vue 样式绑定 vue事件处理器 表单控件绑定 父子组件通信 过渡效果 vue经验总结 javascript ...

  5. IE6的那些css常见bug(汇总)

    IE6的那些css常见bug(汇总) 我的微博终于在前几天建立了 虽说很早之前就知道博客园这个地方 但怕自己不能坚持去写一些东西一直没有建.这几天 我做了这个决定 把我的博客建起来 每周发一些看到的, ...

  6. CSS定位与布局:浮动

    浮动的特点   浮动(float)属性提出的作用是实现文字的环绕效果,一个元素浮动后,会脱离普通流.主要的特点如下: 浮动的元素会向左或者向右移动直到它的外边缘接触容器框(containing blo ...

  7. nginx实现动态分离,解决css和js等图片加载问题

    改帖专门为使用nginx,通过nginx把请求转发到web服务器再返回客户端的时候,解决css和js和图片加载不出来的问题. 如果没安装nginx,请访问一下地址进行安装 http://www.cnb ...

  8. CSS定位(CSS定位概述、相对定位、绝对定位、浮动)

    CSS 定位属性 CSS 定位属性允许你对元素进行定位. 属性 描述 position 把元素放置到一个静态的.相对的.绝对的.或固定的位置中. top 定义了一个定位元素的上外边距边界与其包含块上边 ...

  9. CSS定位深入理解 完全掌握CSS定位 相对定位和绝对定位

    其实前面的标准流和浮动流都很理解,就是定位不太好理解,特别是相对定位和绝对定位,很多刚开始学的同学不好区分.因此这里,小强老师和大家一起分享CSS定位的学习. 通过我们前面的学习,我们网页布局方法: ...

随机推荐

  1. 线程之threading

    多任务:操作系统同时运行多个任务 线程:一个程序运行起来之后一定有一个执行代码的东西,该东西即为线程 线程是操作系统调度执行的最小单位   * 并发:指的是任务数多余cpu核数,通过操作系统的各种任务 ...

  2. MIT Molecular Biology 笔记7 调控RNA

    视频  https://www.bilibili.com/video/av7973580/ 教材 Molecular biology of the gene 7th edition  J.D. Wat ...

  3. 正则表达式Regular expressions

    根据某种匹配模式来寻找strings中的某些单词 举例:如果我们想要找到字符串The dog chased the cat中单词 the,我们可以使用下面的正则表达式: /the/gi 我们可以把这个 ...

  4. JQuery设置和去除disabled属性 与 display显示隐藏

    //两种方法设置disabled属性 $('#areaSelect').attr("disabled",true); $('#areaSelect').attr("dis ...

  5. noip2017d1t3

    其实是参考洛谷上某篇题解的思路: 先求出两个dis数组表示从1走和从n走的最短路: 转移方程:dp[v][dis1[u]-dis1[v]+w+j]+=dp[u][j]; 转移顺序要注意一下呢,肯定是先 ...

  6. 20155326 实验四 Android程序设计实验报告

    20155326 实验四 Android程序设计实验报告 实验内容 1.基于Android Studio开发简单的Android应用并部署测试; 2.了解Android.组件.布局管理器的使用: 3. ...

  7. TBB的学习

    1. TBB简介 TBB ( Thread Building Blocks, 线程构建模块) 是Intel公司开发的并行编程开发的工具.它支持Windows,OS X, Linux平台,支持的编译器有 ...

  8. Scala_类

    类 简单类 最简单的类的定义形式是: class Test1 {  //这里定义类的字段和方法} 可以使用new关键字来生成对象 var test = new Test1() 给类增加字段和方法 Un ...

  9. iOS计算UIWebView的高度和iOS8之后的WKWebView的高度问题

    当我们涉及到webView和自定义控件结合的时候,例如一个资讯详情,上半部分是webView,下面位置想加上我们的自定义控件,可可以计算出webView的高度,在刷新界面. 下边是计算UIWebVie ...

  10. 【图数据结构的遍历】java实现广度优先和深度优先遍历

    [图数据结构的遍历]java实现广度优先和深度优先遍历 宽度优先搜索(BFS)遍历图需要使用队列queue数据结构: 深度优先搜索(DFS, Depth First Search)的实现 需要使用到栈 ...