事因

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

灵感

下班后的路上在想,虽然我们不知道是哪段代码引起的,但如果我们能够分析出什么时候会发生这件事,那就解决了一半的问题,而什么时候会发生我们是可以知道的,在问出这个问题的时候就可以知道,既然是因为在弹出层中滑动引起的,那么也就是说在滚动的时候会发生这件事。而我的想法就是在滚动事件中加一个判断,如果是正常滚动那么就不做任何处理,而如果是由其他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. C++指针一

    指针也是变量,占有内存空间,用来保存内存地址. 指针也是一种数据类型,指针是一种数据类型,是指它所致内存空间的数据类型. 指针变量和它指向的内存块是两个不同的概念 *p操作内存 在指针声明时,*号表示 ...

  2. 有趣的HTML5 CSS3效果

    iphone6 外观:http://www.html5tricks.com/demo/css3-iphone6/index.html 天气图标:http://www.html5tricks.com/d ...

  3. Reorder the Books -- hdu -- 5500

    http://acm.hdu.edu.cn/showproblem.php?pid=5500 Reorder the Books Time Limit: 4000/2000 MS (Java/Othe ...

  4. (数学)Knight's Trip -- hdu -- 3766

    http://acm.hdu.edu.cn/showproblem.php?pid=3766 Knight's Trip Time Limit: 2000/1000 MS (Java/Others)  ...

  5. java注解学习(1)注解的作用和三个常用java内置注解

    今天,记录一下自己学习的关于注解方面的知识. Annotation是从JDK5.0开始引入的新技术 Annotation的作用: -不是程序本身,可以对程序做出解释(这一点和注释没什么区别) -可以被 ...

  6. Java Map释放内存置null以及调用clear()的区别

    今天自己在总结map的时候,想到了在释放Map对象空间的时候就有使用过将Map对象置null,也有时候会调用clear()将Map中的数据清除,那么它们都有什么区别呢? Map<Integer, ...

  7. jQuery插件初级练习2答案

    html: $.font($("p"),"30px").html("变化了") jQuery: $.extend({ font:functi ...

  8. ASP.NET MVC5 高级编程-学习日记-第一章 入门

    1.1 ASP.NET MVC 简介 ASP.NET是一种构建Web应用程序的框架,它将一般的MVC(Model-View-Controller)模式应用于ASP.NET框架. 1.1.1 MVC模式 ...

  9. 纸壳CMS主题增强,支持主题中加入模板

    背景 在之前,纸壳CMS的主题仅仅只是CSS样式,并不支持在主题下使用模板来构建不同的HTML结构.现在我们对主题功能做了增强,可以在主题下添加各自的模板,这样在制作主题时,就会更加自由.不仅如此,新 ...

  10. 堆排序(大顶堆、小顶堆)----C语言

    堆排序 之前的随笔写了栈(顺序栈.链式栈).队列(循环队列.链式队列).链表.二叉树,这次随笔来写堆 1.什么是堆? 堆是一种非线性结构,(本篇随笔主要分析堆的数组实现)可以把堆看作一个数组,也可以被 ...