Java工程师可能不知道的那些FE潜规则

开发 后端
可如今写一个稍微复杂点的小应用,要兼容所有浏览器,才发现真是太难了,难怪FE是一个独立的工种,有别于我们这些Java工程师了。

写了一个多月JavaScript,感觉如今可不比几年前只有IE6的年代,而且过去只是用JS写个Ajax或者是简单的表单验证,可如今写一个稍微复杂点的小应用,要兼容所有浏览器,才发现真是太难了,难怪FE是一个独立的工种,有别于我们这些Java工程师了。如果你也不是专业FE,那么估计也会跟我一样在这些地方翻船,或许你所遇到的情况比我这些还多,那么欢迎补充。

1 首先是最简单的select标签,就有诸多不兼容:

A、 cloneNode方法,对于非IE浏览器没有问题,对于IE浏览器,我遇到的问题包括:

1)option selected的会clone不过去,然后会将***个option作为selected值

2)事件clone也会有问题

B、Readonly:对于IE6,可以通过以下方法将select设为readonly:

obj.onbeforeactive=function(){return false}
obj.onfocus=function(){obj.blur();}
obj.onmouseover=function(){obj.setCapture();}
obj.onmouseout=function(){obj.releaseCapture();}

对于其他浏览器,我采用的是元素替代法,动态创建一个input标签,把值赋给它,然后将select隐藏。

C、select的z-index对于IE6无效,网上有很多关于这个讨论,jQuery采用一个iframe搞定

D、动态添加option的方法不同,这个网上一搜一大堆

E、对于onclick和onchange的响应不同,在FF下可以在onclick select时动态读取option值然后构建option,然后选中一个值后执行onchange事件,但是IE下不能这样做。

2 css对offsetWidth之类的理解不同

http://newleague.iteye.com/blog/765535

3 对于vertical-align baseline的理解不同:

http://w3help.org/zh-cn/causes/RD1016

4 设置背景色

element.style.backgroundColor

在firefox下想改变颜色,必须先设为null,再设为其他颜色才行,即先取消原来的颜色。

在IE下,想取消颜色,必须设为''才行,而换其他颜色,无需先去掉之前的颜色,而如果你设成了null,反倒不行了。

5 不同浏览器去padding的理解不同

6 不同浏览器对强制换行和强制不换行的理解不同:

http://www.cftea.com/c/2009/01/QPDZU40MNW8FYYG3.asp

最恶心的是对于IE6,如果是<td><span>我是蚊子</span></td>,那么在td上写了word-break:keep-all依然无效,必须在span上也写。
 

7 获得head节点的方式不同

在Firefox下可以用window.head,而所有浏览器都兼容的方式是document.getElementsByTagName('head')[0]

8 往head上添加css code的方法不同,也就是动态添加<style>标签。

IE下可以用var style=document.createStyleSheet();style.cssText=cssCode;

而有文章说,在Windows上的IE,用createStyleSheet返回的是styleElement的styleSheet,而在Mac上返回的是styleElement自己。

在其他浏览器下需要document.createElement('style');

然后还有区分是否具有styleSheet属性。

这个很容易搜到。

9 对于onchange事件,firefox浏览器可以注册在table,div等组件上,然后通过冒泡,拦截input,select等发出的事件,而IE不行,必须绑定到相应的组件上

10 将input设为readonly=true,其依然会响应keypress,keyup,keydown,onblur事件

11 IE和非IE对于停止冒泡和取消默认行为的方法不同

12 大家都知道IE和非IE在动态添加事件时使用的方法不同,IE是attachEvent,其他是addListener,然后参数也不同。更重要的是如果一个控件绑定了多个function,他们绑定和执行的顺序是不同的,IE是跟绑定顺序相反,其他是跟绑定顺序相同

13 获得当前事件不同,一个是window.event一个是直接接受event

14 FF下执行offset系列非常慢,但是IE下比较快,而IE的改变CSS的执行非常慢。

Firefox6比Firefox3.6速度快的多,相差好几百倍(针对一个400行*50列的表格的JS处理)

15 如果大量动态改变css,那么使用document.createDocumentFragment,然后将需要修改样式的Dom获取出来appendChild到这个临时的fragment上,修改完css后再append回去即可,这样性能能差好几百倍。

16 浏览器加载网页时,顺序读取html,遇到外部js链接会读进来,然后按顺序执行,边解释边执行,而对于外部css,图片等则是启动另外的线程连接服务器去获取。

IE对于CSS引入有限制,我没试过,但有篇文章讨论:http://blog.csdn.net/ydshang/article/details/4158211

17 表格定位某一行,可以通过改变scrollTop来实现,当然如果出现了滚动条的话

18 IE的Dom用完要记得释放,可以在unload方法中,否则会出现内存泄露

19 unload方法在各个浏览器里各不相同,我之前的文章里有介绍。http://sslaowan.iteye.com/blog/1128209

20 我知道了为什么FE最喜欢的浏览器是FF,最讨厌的是IE6,恨不得IE6去死,其他IE也不怎么样。但是Chrome,Opera也各有各的bug

21 Ajax当使用同步模式时,如果访问的链接是错误的,那么FF会在控制台报错,而IE会直接弹出个对话框,然后就崩溃了。

22 FF支持document.getElementsByClass等方法,IE不支持,可以自己写一个。

23 trim方法在IE和FF下不同,需要自己写一个,可以用正则表达式

24 动态设置元素的css class在IE和非IE浏览器下也不同

25 有时本地字体库会影响你的字体,大小等显示,但是有时甚至会影响你的布局

26 字符串也可以使用><等符号比较大小,但是是字符串比较,不要被骗了。

27 JS中this问题非常让人困惑

28 判断浏览器可以有很多方法,主流是两大类,agent判断法和特性法,后者好像更推荐

29 JS是面向对象语言,对象.属性=值 只影响当前对象,而对象.prototype.属性则影响整个类。非IE浏览器可以覆盖DOM对象的类方法,但是IE不行。

30 getComputedStyle,获得外部添加的css,FF支持,IE不支持,具体看这篇文章http://www.jb51.net/article/16128.htm

31 IE和Chrome支持outerHTML方法,其他浏览器没有。相关讨论:http://walsh.iteye.com/blog/261966,http://stackoverflow.com/questions/1700870/how-do-i-do-outerhtml-in-firefox

32 还有一个特悲剧的,IE下会把document.[formname.]控件Id当成那个控件,如果把一个控件比如input的id设为了submit,那么form.submit()就会报错。

2011-8-2***dd

33 如果利用全角空格进行布局时,Firefox支持,而IE会去除只剩一个,但是是在某些情况下的,具体看这篇文章:http://w3help.org/zh-cn/causes/BT1025

34 透明度:

filter:alpha(opacity=0); /* IE */
-moz-opacity:0.3; /* Moz + FF */
opacity: 0.3;

至于用不用var的区别,undefined和null的区别,Ajax构建的不同方式,这些一般的Java程序员都了解了。

很多Java程序员也会使用JS框架,比如JQuery,Extjs和Dojo,她们都帮我们屏蔽了很多兼容性问题。Dojo提供了Java一样的面向对象机制。

抛砖引玉,你还遇到过什么陷阱,那些FE都知道,而我们Java工程师不知道?

有同学要求例子,有些只是小知识,有了链接,那么给一个我做的过程中写的实验程序吧,主要是验证select,还有readonly之后的input对于keypress等事件的响应:

  1. <head>    
  2. <script>    
  3.     function addListener(element,e,fn){    
  4.      if(element.addEventListener){    
  5.           element.addEventListener(e,fn,false);    
  6.      } else {    
  7.           element.attachEvent("on" + e,fn);    
  8.      }    
  9.    }    
  10.        
  11.    function getEventSource(event){    
  12.         event = window.event?window.event:event;     
  13.         var source = event.target || event.srcElement;       
  14.         return source;    
  15.   }    
  16.     
  17.       
  18.   function init(e){    
  19.     var provChoicedocument.getElementById('prov');    
  20.      fillPro(provChoice);         
  21.      addListener(provChoice,'change',fillCity);    
  22.     var coChoicedocument.getElementById('country');    
  23.      addListener(coChoice,'change',function(){alert('a');});    
  24.     var selects=document.getElementsByTagName('select');        
  25.     for(var i=0;i<selects.length;i++){    
  26.        selects[i].cloneNode=function(deep){    
  27.         var temp=document.createElement('div');    
  28.         temp.innerHTML=this.outerHTML;    
  29.         return temp.childNodes[0];          
  30.       }    
  31.           
  32.           
  33.    }        
  34.        
  35.     document.getElementById('cloneCo').appendChild(coChoice.cloneNode(true));    
  36.     var coTDdocument.getElementById('co');    
  37.     document.getElementById('r1').appendChild(coTD.cloneNode(true));    
  38.         
  39.     document.getElementById('abc').readOnly=true;    
  40.     document.getElementById('abc').onkeydown=function(e){    
  41.          e.preventDefault();    
  42.          e.stopPropagation();    
  43.     }    
  44.         
  45.     document.getElementById('abc').onkeypress=function(e){    
  46.         alert('b');    
  47.     }    
  48.         
  49.     document.getElementById('abc').onchange=function(e){    
  50.         alert('c');    
  51.     }    
  52.         
  53.     document.getElementById('abc').onblur=function(e){    
  54.         alert('d');    
  55.         document.getElementById('abc').value='add';    
  56.     }    
  57.   }    
  58.      
  59.   function fillPro(pro){    
  60.       pro.options[0]=new Option('BJ','北京');    
  61.       pro.options[1]=new Option('TJ','天津');    
  62.       pro.options[2]=new Option('HLJ','黑龙江');    
  63.       pro.options[3]=new Option('SH','上海');    
  64.   }    
  65.       
  66.   function fillCity(e){    
  67.        var cdocument.getElementById('city');    
  68.        if( document.getElementById('prov').value=='黑龙江'){    
  69.          c.options[0]=new Option('HRB','哈尔滨');    
  70.          c.options[1]=new Option('MDJ','牡丹江');    
  71.          c.options[2]=new Option('QQHR','齐齐哈尔');    
  72.          c.options[3]=new Option('JMS','佳木斯');    
  73.        }    
  74.          
  75.          
  76.   }    
  77.        
  78. </script>    
  79. </head>    
  80. <body onload='init(event)'>    
  81.  <table>    
  82.    <tr id='r1'>    
  83.      <td id='co'>    
  84.        <select id='country' name='country'>    
  85.         <option value='UK'>UK</option>    
  86.         <option value='USA'>USA</option>    
  87.         <option value='CHINA' selected>China</option>    
  88.        </select>    
  89.      </td>    
  90.      <td>    
  91.        <select id='prov' name='prov'></select>    
  92.      </td>    
  93.      <td>    
  94.        <select id='city' name='city'></select>    
  95.      </td>    
  96.      <td id='cloneCo'></td>    
  97.      <td>    
  98.        <input id='abc' value='0'  onkeypress='return alert("a1"); '/>    
  99.      </td>           
  100.    <tr>    
  101.  <table>    
  102.     
  103. </body>    
  104. </html>   

原文:http://sslaowan.iteye.com/

【编辑推荐】

  1. 深入Java,初探JVM
  2. 电影《Java风云》预告片
  3. Flex与Java中的Object交互
  4. Flex前端与Java服务端交互,反射机制挑大旗
  5. 基于Java的HBase客户端编程
责任编辑:陈贻新 来源: sslaowan
相关推荐

2012-11-23 10:57:44

Shell

2015-08-13 09:03:14

调试技巧

2019-11-20 10:25:06

sudoLinux

2021-01-05 11:22:58

Python字符串代码

2020-01-29 19:40:36

Python美好,一直在身边Line

2015-11-02 09:16:08

2023-02-27 09:20:24

绝对定位CSS

2023-01-29 09:46:47

Dialog弹窗模态

2019-11-25 14:05:47

Python装饰器数据

2014-12-08 10:39:15

2021-07-12 07:59:06

安全 HTML 属性

2021-12-17 00:10:00

ChromeDevtools功能

2010-08-06 13:15:35

2010-07-26 13:24:11

2020-05-09 08:48:21

JavaScript原生方法代码

2011-02-14 16:11:44

2010-07-21 12:37:11

Linux用户

2015-05-14 15:59:33

DockerLinux容器管理工具

2010-08-10 09:13:49

Linux用户

2018-05-10 11:50:13

Docker容器冷知识
点赞
收藏

51CTO技术栈公众号