DOM的小事情 NO.2
上篇文章写完后,我突然觉得有点不对劲。原因是我在写日常的时候发现了一个问题,当时我要把某个元素隐藏起来,我写了如下的代码:(别笑,这行代码让我露馅了,我是新手。)
elem.style = "display:none";
然后在各个浏览器都不行。我当时的想法是会不会是“property”和"attribute"的问题,正如我上篇文章所提那样。不管怎样,我换了种写法:
elem.setAttribute('style','display:none');
居然在Chrome下和FF下有了效果,而在IE下却挂了。我当时蛮郁闷:
第一,我上篇文章说了,Property是动态值,应该根据Property的值来显示,第一种写法是设置Property啊,为啥挂了,而设置Attribute却OK了?
第二,IE肿么挂了?
为了回答这两个问题,我重新去寻找资料,网上这些资料也不多,我只好看DOM规范去了。
我整理出一下结论:(由于英文不好,如有错误,请大声骂娘并告诉我)
1.SourceCode、HTML文档元素、DOM元素的联系
1.SourceCode应该最好理解,就是从服务器下载下来的文本,一但下载下来了,就不会改变了。
2.HTML文档元素我很难去描述,形象点说就是你打开Firebug之后看到的。你修改某个属性页面上会有相应的变化。
3.DOM规范其实是一套接口,DOM元素是实现了这套接口的实例。它可以允许脚本通过这套接口操纵HTML文档元素。
2.Property和Attiribute的关系
每个js对象都会有属性Property,而Attribute是HTML文档的属性(attirbute)。而DOM规定了DOM元素可以有快捷方式去操作HTML元素的属性,所以有些DOM元素的property可以直接操作HTML的属性attribute。这里要注意的是:
1.HTML元素的有些属性。这些属性包括id,name,class等等,当显然不包括一些你自定义的属性例如myid等等了。
2.快捷方式。这表明了,property还是property,attribute还是attribute。
例子:
<!--如果有以下代码-->
<input id = "3" myid = "4" type = "text" />
<script>
/*省略一些代码*/
console.log(input.id) //输出3
console.log(input.myid)//undefined
input.id = "4"; //文档的id确实改变了
input.myid2 = "5"; //对文档不会有影响!!
</script>
3.Current Value(当前值)和Property、Attribute的关系
这部分是我上篇讲得有问题。我把Property直接简单等价于Current Value是不对的。
Current Value这个概念是form元素才有的,也就是<input />里面才有的。规范里面的意思是,用户输入的值叫做current value,他不会改变HTML文档元素的属性(Attribute),我们可以用过Dom元素的property去获取。
4.style与property和attribute的关系。
这部份将解决我之前编码遇到的问题。
我刚才提到,Property和Attribute之间有快捷方式,那style这个属性有没有快捷方式?我认为是有半个。
elem.style; //返回的是一个CSSStyleDeclaration
elem.getAttribute('style'); //返回的是一个DOMString
上面的代码,我们可以看到,返回了不同的对象。
DOMString好理解,就是一个UTF-16的String类型,而CSSStyleDeclartion是什么?
CSSStyleDeclaration说简单点就是一个CSS块的模块单位,里面包括了这个元素的样式块。如果我们要知道这个块里面定义的background是什么,我们可以通过elem.style.background来访问。所以当时我想设置元素dispaly:none的时候出了大错。elem.style不接受字符串作为内容,我应该要elem.style.display = "none";
这样,我们可能会以为style在Property和Attribute之间没有快捷方式,这样也不对,因为他们的确是同步的,只是表现方式不一样,只能算半个。
这里还要讨论一个问题,为什么我当时写elem.setAttribute('style','display:none');的时候在所有浏览器都可以,就IE不行?
其实我上篇文章也有提到,因为IE有bug,他不区分attribute和property,所以,在IE下elem.getAttribute('style')的时候返回的居然CSSStyleDeclaration类型的实例。自然,setAttribute的同时,你无法为一个CSSStyleDeclaration设置一个字符串。
最终我的解决方案是使用elem.style.display = "none"来解决的。
关于IE这个bug,我再多说一句,你猜下面的代码在IE会不会挂,为什么?
elem.setAttribute('class',"myclass");
//IE会挂,其他不会。
//但是elem.setAttribute('className','myclass');居然在IE下可行。
//当然,其他浏览器是不行的。
至于为什么,和怎么解决,你们都懂的。
5.关于CSSStyleDeclaration。
这部份不好说我刚才没讲细,因为不好讲,要涉及到整个CSS的所有接口,需要另开文章。有需要的童鞋,不要犹豫,直接看规范吧。
这里没讲好,抱歉了。