洞悉特性、属性和样式
2016-12-21 21:46
260 查看
在DOM特性和属性之间不仅会有一些非常细微的行为差别,在其他一些方面也会有很多bug以及跨浏览器问题。
但特性和属性都是很重要的概念:特性是DOM构建的一个组成部分,而属性是元素保持运行时信息的主要手段,并且通过属性可以访问这些运行时信息。看个例子。
在上述代码中,我们创建一个图像标签,获取他的引用,并将他的src属性修改为一个新值,这看起来非常简单,但是我们运行测试验证一下。
测试src属性的值就是我们新赋的值,毕竟如果我们赋值x=213,当然希望x的值就是213,我们并没有改变其特性(attribute),所以它应该保持不变,对吧?
但当我们两个测试都失败了,我们看到src属性的值不是我们所赋予的值,而是类似如下的值
给一个属性赋值,难道不应该去往那个属性就是所赋予的值吗?更奇怪的是,即使我们并没有改变元素上的特性(attribute),失败的测试表明,src的特性值已经变成如下内容了:
到底发生了什么事情,我们将检查与元素属性和特性相关的所有浏览器难题,我们会研究为什么结果不是我们所预期的。这同样适用于css和元素样式,构造一个动态web应用程序时,我们会在设置或获取元素样式方面遇到很多的困难,我们讨论一下元素的样式处理知识。
测试显示了,这个不幸的特性会导致标签数据的损失。
我们可以用获取描述元素特性本身的原始DOM节点,该节点任然没有被浏览器所修改。可以使用getAttributeNode(‘action’).nodeValue来进行获取action特性的值,该问题不能被认为是一个bug,因为这是浏览器预期的行为,当元素的引用很容易使用像document.getElementById()或其他类似的方法获取到时,该问题就很具有破坏性。
通过DOM的原始节点找出该标签的原始值。我们要对该值进行验证,测试失败,因为该值被转为为规范的URL值了。
对于隐藏的元素,如果希望获取它在非隐藏状态时的尺寸,我们可以使用一个技巧,暂时取消元素的隐藏,然后获取值,然后再将其隐藏,我们希望那这种做法不会有明显的视觉效果,而是只在幕后做,如何才能将一个隐藏的元素,在不可见的情况下变为不隐藏的呢?
方法如下:
1.将display属性设置为block
2.将visibility设置为hidden
3.将position设置为absolute
4.获取元素尺寸
5.恢复先前更改的属性
将display属性修改为block,可以让我们获取offsetHeight和offsetWidth的真实值,但他将元素变成显示状态而因此可见,要让该元素不可见,需要将visibility设置为hidden,但是这种做法将导致在元素的位置上显示一片空白,所以我们需要将position属性设置为absolute,以便将元素移出正常的显示流。代码实现如下。
这个函数不论是在元素上显示声明的,还是继承自样式表的,都可以获取得到。还要注意,两种方式都指定了color属性,但是返回的是在元素上显式指定的值,元素的style特性指定的样式优先级永远高于继承的样式,即便继承的样式标记为!important也没用。
在处理样式属性的时候,还有一个问题我们需要注意:混合属性,css允许我们使用快捷方式表示混合属性,比如border属性,不必强迫单独对四个边框都指定颜色,宽度,边框样式,只需要使用如下规则即可:
注意,在获取属性的时候,我们需要检索的是底层的单个属性,我们不能检索border,而是应该检索像border-top-color和border-top-width这样的属性,就想在示例中所做的那样。
但特性和属性都是很重要的概念:特性是DOM构建的一个组成部分,而属性是元素保持运行时信息的主要手段,并且通过属性可以访问这些运行时信息。看个例子。
var img = document.getElementsByTagName('img')[0]; var newSrc = 'img/thumb.jpg'; image.src = newSrc;
在上述代码中,我们创建一个图像标签,获取他的引用,并将他的src属性修改为一个新值,这看起来非常简单,但是我们运行测试验证一下。
img.src === newSrc; img.getAttribute('src') === 'img/goods.webp';
测试src属性的值就是我们新赋的值,毕竟如果我们赋值x=213,当然希望x的值就是213,我们并没有改变其特性(attribute),所以它应该保持不变,对吧?
但当我们两个测试都失败了,我们看到src属性的值不是我们所赋予的值,而是类似如下的值
file:///E:/code/bookShopin/img/thumb.jpg"
给一个属性赋值,难道不应该去往那个属性就是所赋予的值吗?更奇怪的是,即使我们并没有改变元素上的特性(attribute),失败的测试表明,src的特性值已经变成如下内容了:
"img/thumb.jpg"
到底发生了什么事情,我们将检查与元素属性和特性相关的所有浏览器难题,我们会研究为什么结果不是我们所预期的。这同样适用于css和元素样式,构造一个动态web应用程序时,我们会在设置或获取元素样式方面遇到很多的困难,我们讨论一下元素的样式处理知识。
DOM特性和DOM属性
在访问元素的特性值时,有两种选择:使用传统的DOM方法叫getAttribute和setAttribute,或使用DOM对象上与之对应的属性。举例来说,一个元素保存在变量e中,要获取其id特性的话,我们可以使用如下方式,e.getAttribute('id'); e.id
性能注意事项
总的来说,属性的访问速度比相应的DOM特性方法的访问速度要快,特别是在IE中,经过在多个浏览器上测试,属性的滑入和设置操作几乎总比getAttribute()和setAttribute()快。所以要提高性能,我们可能想要实现一个方法,在属性值存在的时候就访问属性值,属性值不存在的时候利用DOM方法作为后备,考虑如下代码。(function () { var translations = { 'for': 'htmlFor', 'class': 'className', readonly: 'readOnly', maxlength: 'maxLength', cellspacing: 'cellSpacing', rowspan: 'rowSpan', colspan: 'colSpan', tabindex: 'tabIndex', cellpadding: 'cellPadding', usemap: 'useMap', frameborder: 'frameBorder', contenteditable: 'contentEditable' }; window.attr = function (element, name, value) { var property = translations[name] || name; var propertyExists = typeof element[property] !== 'undefined'; if(typeof value !== 'undefined') { if(propertyExists){ element[property] = value; }else { element.setAttribute(name, value); } } return propertyExists ? element[property] : element.getAttribute(name); } })();
跨浏览器的attribute问题
五大浏览器都会将表单input元素的id和name特性作为元素的属性值进行引用,产生的这些属性,会主动覆盖form元素上已经存在的同名属性。<input type="text" for="sufubo" id="test"> <form id="testForm" action="/" > <input type="text" id="id"/> <input type="text" name="action"/> </form> <script type="text/javascript"> var form = document.getElementById('testForm'); form.id === <input type="text" id="id"/> form.action === <input type="text" name="action"/> </script>
测试显示了,这个不幸的特性会导致标签数据的损失。
我们可以用获取描述元素特性本身的原始DOM节点,该节点任然没有被浏览器所修改。可以使用getAttributeNode(‘action’).nodeValue来进行获取action特性的值,该问题不能被认为是一个bug,因为这是浏览器预期的行为,当元素的引用很容易使用像document.getElementById()或其他类似的方法获取到时,该问题就很具有破坏性。
URL规范化
在所有的现代浏览器中,有一个违反最少意外原则的特性,在访问一个引用了URL的属性时,该URL值会自动将原始值转换成完成规范的URL。<a href="package.json" id="testSubject">self</a> <script type="text/javascript"> var link = document.getElementById('testSubject'); var linkHref = link.getAttributeNode('href').nodeValue; link.href === 'package.json' </script>
通过DOM的原始节点找出该标签的原始值。我们要对该值进行验证,测试失败,因为该值被转为为规范的URL值了。
type特性
另外还有一个IE特性,IE8以及之前的版本对元素的type特性的影响,没有任何合理的解决方案,一旦元素被插入到文档,他的type特性就不能再改变了。如果修改,IE就会抛出一个异常。样式属性命名
我们编写一个简单的api自动将样式转化为驼峰格式//访问样式的简单方式 function style(element, name, value) { name = name.replace(/-([a-z])/ig, function (all, letter) { return letter.toUpperCase(); }); if(typeof value !== 'undefined') { element.style[name] = value; } return element.style[name]; }
对于隐藏的元素,如果希望获取它在非隐藏状态时的尺寸,我们可以使用一个技巧,暂时取消元素的隐藏,然后获取值,然后再将其隐藏,我们希望那这种做法不会有明显的视觉效果,而是只在幕后做,如何才能将一个隐藏的元素,在不可见的情况下变为不隐藏的呢?
方法如下:
1.将display属性设置为block
2.将visibility设置为hidden
3.将position设置为absolute
4.获取元素尺寸
5.恢复先前更改的属性
将display属性修改为block,可以让我们获取offsetHeight和offsetWidth的真实值,但他将元素变成显示状态而因此可见,要让该元素不可见,需要将visibility设置为hidden,但是这种做法将导致在元素的位置上显示一片空白,所以我们需要将position属性设置为absolute,以便将元素移出正常的显示流。代码实现如下。
(function () { var PROPERTES = { position: 'absolute', visibility: 'hidden', display: 'block' }; window.getDimensions = function (element) { //把原先的保存一下 var previous = {}; for(var key in PROPERTIES) { previous[key] = element.style[key]; element.style[key] = PROPERTIES[key]; } var result = { width: element.offsetWidth, height: element.offsetHeight } for (key in PROPERTIES) { element.style[key] = previous[key]; } return result; } })();
获取计算样式
function fetchComputedStyle(element, property) { if(window.getComputedStyle) { var computedStyles = window.getComputedStyle(element); if(computedStyles) { property = property.replace(/([A-Z])/g, '-$1').toLowerCase(); return computedStyles.getpropertyValue(property); } }else if (element.currentStyle) { property = property.replace( /-([a-z])/ig, function (all, letter) { return letter.toUpperCase(); }); return element.currentStyle[property]; ) } }
这个函数不论是在元素上显示声明的,还是继承自样式表的,都可以获取得到。还要注意,两种方式都指定了color属性,但是返回的是在元素上显式指定的值,元素的style特性指定的样式优先级永远高于继承的样式,即便继承的样式标记为!important也没用。
在处理样式属性的时候,还有一个问题我们需要注意:混合属性,css允许我们使用快捷方式表示混合属性,比如border属性,不必强迫单独对四个边框都指定颜色,宽度,边框样式,只需要使用如下规则即可:
border: 1px solid crimson;
注意,在获取属性的时候,我们需要检索的是底层的单个属性,我们不能检索border,而是应该检索像border-top-color和border-top-width这样的属性,就想在示例中所做的那样。
总结
在遇到跨浏览器兼容性问题时,获取和设置DOM特性、属性以及样式,可能不是浏览器javaScript开发中最严重的问题,但确实有它的问题,值得庆幸的是,我们学到了可以处理这些问题的方式,使得代码可以兼容跨浏览器,而无需使用浏览器探测。相关文章推荐
- JavaScript特性(attribute)、属性(property)和样式(style)
- JavaScript特性(attribute)、属性(property)和样式(style)
- JavaScript特性(attribute)、属性(property)和样式(style)
- Flex的Combobox组件(Prompt属性、文字过长...特性)
- Dom样式操作-属性操作
- C#类特性和属性特性
- jquery中的属性和样式设置
- C#3.0新特性(三)-详说自动属性和匿名类型
- 区分元素特性attribute和对象属性property
- table表设置了class属性,如何修改里面的tr或者td样式
- JavaScript之再谈对象之属性的特性
- scrollbar属性、样式详解
- js返回最终样式函数,兼容IE和DOM,设置参数:元素对象、样式特性
- 利用css的cursor属性改变鼠标的样式
- JavaScript DOM中 改变样式属性,实现动画效果
- 利用数组特性便利json对象中属性
- JavaScript DOM中 改变样式属性,实现动画效果 2
- javacsript对象属性的特性和对象的三个属性
- input 标签 修改 disabled 属性默认样式(适配安卓 IOS)
- 怎么确定要对DIV设置什么CSS属性样式