【HTML5&CSS3进阶05】CSS如何成功的“阻塞”JS程序

一般情况下CSS不会直接影响JS的程序逻辑,但是以CSS实现动画的话,这个便不太确定了,这个故事发生在与UED迁移全局样式的过程。

曾经我有一段实现弹出层隐藏动画的代码是这个样子的:

1 if (this.needAnimat && typeof this.animateHideAction == ‘function‘ && this.status != ‘hide‘) {
2   this.animateHideAction.call(this, this.$el);
3 } else
4   this.$el.hide();

在所有组件中,如果设置了animatHideAction回调的,便会执行其中的动画逻辑,针对弹出层来说:

① alert

② loading

③ toast

④ 底部弹出层

等组件中动画效果各不相同:

① 动画显示时下沉,隐藏时上浮

② 动画渐隐渐显

③ 组件底部弹出

......

针对通用的动画,一般框架会提供一段CSS类做处理,不满足的情况,各个业务团队便需要自己封装:

 1 cm-fade-in, .cm-fade-out, .cm-down-in, .cm-down-out, .cm-up-in, .cm-up-out {
 2   -webkit-animation-duration: 0.3s;
 3           animation-duration: 0.3s;
 4   -webkit-animation-fill-mode: both;
 5           animation-fill-mode: both;
 6 }
 7 ......
 8 @keyframes fadeOut {
 9   0% {
10     opacity: 1;
11     -webkit-transform: scale(1);
12             transform: scale(1);
13   }
14   100% {
15     opacity: 0;
16     -webkit-transform: scale(1.185);
17             transform: scale(1.185);
18   }
19 }
20 ......

这个时候我们要实现一个居中弹出层渐隐的效果事实上只需要这样做:

1 el.addClass(‘cm-fade-out‘);
2
3 el.one($.fx.animationEnd, function () {
4   el.removeClass(‘cm-fade-out‘);
5   el.hide();
6 });

在动画结束后将对应的动画class移除,再执行真实的hide方法,隐藏dom结构。

其实,我记得是去年的时候我是这么处理这个代码的,当时被一个同事骂了不严谨,今年就使用了animationEnd接口:

1 el.addClass(‘cm-fade-out‘);
2
3 setTimeout(function () {
4   el.removeClass(‘cm-fade-out‘);
5   el.hide();
6 }, 340);

这里问题来了,使用animationEnd与setTimeout去除动画class,或者执行业务真实逻辑,到底哪家强,哪个合适?

第一反应都是认为animationEnd比较合理,于是我最近遇到了一个问题:

请求一个数据,loading一直在那里转,永远不消失了!而且执行了hideLoading的操作,与数据延迟毫无关系

于是我开始愉快的定位,当时搞了一会,发现loading的动画没有执行,仔细一定位,发现css中的动画相关的css丢了,于是造成的结果是:

el.addClass(‘cm-fade-out‘);

这个代码变成了单纯的class增加,并没有执行动画,也就是,animationEnd的事件没有触发,于是没有执行hide方法,所以loading框就一直在那里转

问题定位到了,解决方案就非常简单了,将css的动画加上即可;但是也说明了,这段代码中JS代码逻辑依赖了CSS相关,从而导致了CSS阻塞JS的假象

这里如果使用setTimeout的话虽然感觉没有animationEnd严谨,但是一定会保证这逻辑代码执行,从某种程度来说,似乎更好,这里的优化代码是:

 1 var isTrigger = false;
 2
 3 el.addClass(scope.animateOutClass);
 4
 5 el.one($.fx.animationEnd, function () {
 6   isTrigger = true;
 7   el.removeClass(scope.animateOutClass);
 8   el.hide();
 9 });
10
11 setTimeout(function () {
12   if (isTrigger) return;
13
14   el.removeClass(scope.animateOutClass);
15   el.off($.fx.animationEnd);
16   el.hide();
17 }, 350);

如果animationEnd执行了便不理睬setTimeout,否则便走setTimeout逻辑,也不至于影响业务逻辑,但是这个似乎不是最优解决方案。

因为我没有办法,因为这里得有350ms的延迟,在不存在css动画的时候,似乎整个弹出层消失逻辑都变得2B了起来,比较好的方式是,我在执行动画前检测是否具有该css比较靠谱

所以,javascript检测CSS的某一个className是否存在,似乎变成了关键,但是就算就算能找到具有某class,这个class也未必具有动画属性,或者该属性被篡改

况且使用document.styleSheets方式去判断某个样式class是否存在,经过之前的经验,本身就是大坑,还会有跨域什么的场景,坑死人,比如这个代码:

 1 function getAllSelectors() {
 2   var ret = [];
 3   for (var i = 0; i < document.styleSheets.length; i++) {
 4     var rules = document.styleSheets[i].rules || document.styleSheets[i].cssRules;
 5     for (var x in rules) {
 6       if (typeof rules[x].selectorText == ‘string‘) ret.push(rules[x].selectorText);
 7     }
 8   }
 9   return ret;
10 }
11
12 function selectorExists(selector) {
13   var selectors = getAllSelectors();
14   for (var i = 0; i < selectors.length; i++) {
15     if (selectors[i] == selector) return true;
16   }
17   return false;
18 }
19
20 //调用方式
21 selectorExists(‘.class‘);
22 selectorExists(‘#id‘);

上面的代码,本身比较完善了,但是如果某一个文化跨域的话就完蛋,所以这个方案不靠谱:

① class检测方案本身不靠谱

② 就算class靠谱,也不能保证class就具有动画相关属性,所以也不靠谱!

最终我想到的方案还是对动画属性做检测,检测点主要在动画属性的检测,比如关键属性:

① animation-name

② transition的检测

  1 <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
  2 <html xmlns="http://www.w3.org/1999/xhtml">
  3 <head>
  4   <title></title>
  5   <script id="others_zepto_10rc1" type="text/javascript" class="library" src="http://sandbox.runjs.cn/js/sandbox/other/zepto.min.js"></script>
  6   <style>
  7
  8 .cm-fade-in {
  9   -webkit-animation-name: fadeIn;
 10           animation-name: fadeIn;
 11 }
 12
 13 .cm-fade-out {
 14   -webkit-animation-name: fadeOut;
 15           animation-name: fadeOut;
 16 }
 17
 18 @-webkit-keyframes fadeIn {
 19   0% {
 20     opacity: 0;
 21     -webkit-transform: scale(0.815);
 22             transform: scale(0.815);
 23   }
 24   100% {
 25     opacity: 1;
 26     -webkit-transform: scale(1);
 27             transform: scale(1);
 28   }
 29 }
 30
 31 @keyframes fadeIn {
 32   0% {
 33     opacity: 0;
 34     -webkit-transform: scale(0.815);
 35             transform: scale(0.815);
 36   }
 37   100% {
 38     opacity: 1;
 39     -webkit-transform: scale(1);
 40             transform: scale(1);
 41   }
 42 }
 43 @-webkit-keyframes fadeOut {
 44   0% {
 45     opacity: 1;
 46     -webkit-transform: scale(1);
 47             transform: scale(1);
 48   }
 49   100% {
 50     opacity: 0;
 51     -webkit-transform: scale(1.185);
 52             transform: scale(1.185);
 53   }
 54 }
 55 @keyframes fadeOut {
 56   0% {
 57     opacity: 1;
 58     -webkit-transform: scale(1);
 59             transform: scale(1);
 60   }
 61   100% {
 62     opacity: 0;
 63     -webkit-transform: scale(1.185);
 64             transform: scale(1.185);
 65   }
 66 }
 67 .cm-down-in {
 68   -webkit-animation-name: downIn;
 69           animation-name: downIn;
 70 }
 71
 72 .cm-down-out {
 73   -webkit-animation-name: downOut;
 74           animation-name: downOut;
 75 }
 76
 77 @-webkit-keyframes downIn {
 78   0% {
 79     opacity: 0;
 80     -webkit-transform: translate3d(0, 100%, 0);
 81             transform: translate3d(0, 100%, 0);
 82   }
 83   100% {
 84     opacity: 1;
 85     -webkit-transform: translate3d(0, 0, 0);
 86             transform: translate3d(0, 0, 0);
 87   }
 88 }
 89
 90 @keyframes downIn {
 91   0% {
 92     opacity: 0;
 93     -webkit-transform: translate3d(0, 100%, 0);
 94             transform: translate3d(0, 100%, 0);
 95   }
 96   100% {
 97     opacity: 1;
 98     -webkit-transform: translate3d(0, 0, 0);
 99             transform: translate3d(0, 0, 0);
100   }
101 }
102 @-webkit-keyframes downOut {
103   0% {
104     opacity: 1;
105     -webkit-transform: translate3d(0, 0, 0);
106             transform: translate3d(0, 0, 0);
107   }
108   100% {
109     opacity: 0;
110     -webkit-transform: translate3d(0, 100%, 0);
111             transform: translate3d(0, 100%, 0);
112   }
113 }
114 @keyframes downOut {
115   0% {
116     opacity: 1;
117     -webkit-transform: translate3d(0, 0, 0);
118             transform: translate3d(0, 0, 0);
119   }
120   100% {
121     opacity: 0;
122     -webkit-transform: translate3d(0, 100%, 0);
123             transform: translate3d(0, 100%, 0);
124   }
125 }
126 .cm-up-in {
127   -webkit-animation-name: upIn;
128           animation-name: upIn;
129 }
130
131 .cm-up-out {
132   -webkit-animation-name: upOut;
133           animation-name: upOut;
134 }
135   </style>
136 </head>
137 <body>
138   <script type="text/javascript">
139     var hasAnimationProperty = function (className) {
140       var animateProprtys = [
141       //有什么判断的便新增,暂时只判断animation,不同的动画特性,判断方式不一致
142       //        $.fx.cssPrefix + ‘transition‘,
143         $.fx.cssPrefix + ‘animation-name‘
144       ];
145       var el = $(‘<div></div>‘);
146       $(‘body‘).append(el);
147
148       var i, len;
149
150       //赋予其class
151       el.attr(‘class‘, className);
152
153       for (i = 0, len = animateProprtys.length; i < len; i++) {
154         if (el.css(animateProprtys[i]) != ‘none‘) return true;
155       }
156       s = ‘‘;
157       return false;
158     };
159
160     //false
161     console.log(hasAnimationProperty(‘test‘));
162     //true
163     console.log(hasAnimationProperty(‘cm-up-out‘));
164     //true
165     console.log(hasAnimationProperty(‘cm-up-in‘));
166
167   </script>
168 </body>
169 </html>

核心代码:

 1 var hasAnimationProperty = function (className) {
 2   var animateProprtys = [
 3   //有什么判断的便新增,暂时只判断animation,不同的动画特性,判断方式不一致
 4   //        $.fx.cssPrefix + ‘transition‘,
 5     $.fx.cssPrefix + ‘animation-name‘
 6   ];
 7   var el = $(‘<div></div>‘);
 8   $(‘body‘).append(el);
 9
10   var i, len;
11
12   //赋予其class
13   el.attr(‘class‘, className);
14
15   for (i = 0, len = animateProprtys.length; i < len; i++) {
16     if (el.css(animateProprtys[i]) != ‘none‘) return true;
17   }
18   s = ‘‘;
19   return false;
20 };
21
22 //false
23 console.log(hasAnimationProperty(‘test‘));
24 //true
25 console.log(hasAnimationProperty(‘cm-up-out‘));
26 //true
27 console.log(hasAnimationProperty(‘cm-up-in‘));

如此一来,便能判断该class是否具有样式属性了,但是这个代码还需要扩展,我们今天便到此为止了

时间: 2024-10-14 10:14:23

【HTML5&CSS3进阶05】CSS如何成功的“阻塞”JS程序的相关文章

HTML5 CSS3专题 纯CSS打造相册效果

转载请标明出处:http://blog.csdn.net/lmj623565791/article/details/30993277 今天偶然发现电脑里面还有这样的一个例子,感觉效果还不错,不记得啥时候下载的了,也好久没上w3cfuns了,怀念学习前台的日子,给大家分享下. 效果图: 效果是不是还是很不错的,最主要的是没有使用一行js,这才是亮点. 先看html文件: <body> <div id="gallery"> <h1>纯CSS3相册效果&l

【HTML5&amp;CSS3进阶学习02】Header的实现&#183;CSS中的布局

前言 我们在手机上布局一般是这个样子的: 其中头部对整个mobile的设计至关重要,而且坑也很多: ① 一般来说整个header是以fixed布局,fixed这个产物在移动端来说本身坑就非常多 ② 在Hybrid应用中,Header很多时候扮演了不一样的角色,首先要完成以webview(window)为容器的功能,又要调用native提供的接口 Hybrid中Header的实现往往是一个难点,主要原因是同一套接口,要保证H5站点与native处于不一样的环境调用相同的接口,完成不同的功能 ③ 若

【HTML5&amp;CSS3进阶04】CSS3动画应该如何在webapp中运用

动画在webapp的现状 webapp模式的网站追求的就是一个体验,是HTML5&CSS3浪潮下的产物,抛开体验不说,webapp模式门槛比较高: 而体验优化的一个重点便是动画,可以说动画是webapp的一个亮点.但也是一个难点,一个痛点,主要原因是:移动端手机的碎片化严重. 设备.型号.版本.分辨率等差异导致移动端需要考虑的主流情况达10多种,而Hybrid带来的webview可以让情况更加糟糕 所以说,近两年想在移动端大范围的使用动画,或者使用webapp模式都对团队的能力提出了要求,原因是

【HTML5&amp;CSS3进阶03】Jser与Csser如何一起愉快的翻新老组件

上次,我们形成了两种header的布局,一种flexbox,一种float,最后与身边做重构的同事交流下来,选择了float的布局. 事实上布局的选型不需要我关注,我的参与或者一些意见多数是自我提升,但要说html结构完全控制于csser的话就不一定了 在整个header组件的代码过程中,我与重构同事就一些地方发生了重复的交流,争论,今天就header组件的布局以及功能实现,聊一聊js与css的配合 然后header组件本身是一个老组件,我们顺便探讨下,这类老组件应该如何翻新比较合适. 最初的结

【HTML5&amp;CSS3进阶学习01】气泡组件的实现

前言 气泡组件在实际工作中非常普遍,无论是网页中还是app中,比如: 我们这里所谓气泡组件是指列表型气泡组件,这里就其dom实现,css实现,js实现做一个讨论,最后对一些细节点做一些说明,希望对各位有用 小钗最近初学CSS,这里做一个专题,便于自身CSS提升,文章有不少问题与可优化点,请各位指导 组件分类 单由气泡组件来说,他仍然属于“弹出层”类组件,也就是说其会具有这些特性: ① 布局为脱离文档流 ② 可以具有mask蒙版,并且可配置点击蒙版是否关闭的特性 ③ 可选的特性有点击浏览器回退关闭

05. Web大前端时代之:HTML5+CSS3入门系列~H5 多媒体系

Web大前端时代之:HTML5+CSS3入门系列:http://www.cnblogs.com/dunitian/p/5121725.html ? ? ? ?

html5+css3实现上拉和下拉刷新

<!DOCTYPE html><html><head> <meta http-equiv="Content-Type" content="text/html; charset=utf-8"> <meta name="viewport" content="width=device-width, initial-scale=1.0, user-scalable=0, minimum-sc

HTML5&CSS3初学者指南(1) – 编写第一行代码

介绍 网络时代已经到来.现在对人们来说,每天上网冲浪已经成为一种最为常见的行为. 在网页浏览器中输入一段文本地址,就像http://www.codeproject.com,等待一下,网页就加载到浏览器窗口中.一个典型的网页是由文本.图像和链接组成的.除去内容上的差异,不同网站的网页也具有不同的外观和感受,以实现在网络上建立自己的身份品牌的目的. 如果你也曾想要了解你屏幕上的这些网页是如何被创建出并以各式各样的方式渲染的,那么这里正是你可以了解到这些知识的地方.让我们一起走进在浏览器中创建了这么多

无需Flash录视频——HTML5中级进阶

视频采集 本篇介绍的栗子 都是在chrome 47 版本以上的,低版本的可能会出现白屏和错误. 1.安全环境 随着Chrome版本的升高,安全性问题也越来越被重视,较新版本的Chrome浏览器在调用一些API时需要页面处在安全环境中.本篇文章所介绍的API函数,都需要在安全环境中执行.如果处在非安全环境下 ( http页面 ) 这些API就会有意想不到的问题. 比如 getUserMedia()就会报出警告,并执行出错. 而在设备枚举enumerateDevices()时,虽然不会报错,但是他隐