JavaScript欲速则不达——属性节点

使用 property 和 attribute 方法都可以设置属性但是在有些浏览器却有很大不同。

IE6/7获取href / src 属性值不同

<a href="/lab/index.html">lab</a>
	<img src="http://www.html5jscss.com/wp-content/themes/T1/img/no-has-thumbnail.png" alt="JavaScript欲速则不达——属性节点">
<script>
	var link = document.getElementsByTagName('a')[0];
	var img =  document.getElementsByTagName('img')[0];
	alert(link.getAttribute('href')); 
	alert(img.getAttribute('src'))
</script>
		

IE6/7 返回绝对路径,其他浏览器返回的就是属性值,href / src 设置了啥就返回啥

解决方法就是将 getAttribute() 的第二个参数定义为 2 。

alert(link.getAttribute('href',2)); //和标准浏览器一致
alert(img.getAttribute('src',2))	//和标准浏览器一致
		

IE6/7获取button的value不同

<button value="123">hello</button>
<script>
	var btn = document.getElementsByTagName('button')[0];
	alert(btn.value); // IE6/7返回 hello,其他浏览器返回123
	alert(btn.getAttribute('value')); // 如上
</script>	
		

解决以上问题我们了解 attributes 对象。

attributes对象

console.log(btn.attributes)	
			

输出如下图:

attributes

从以上图我们知道 attributes 包含一下有用的方法:

{
	属性索引: {  },  
	length:{ number },  // 属性数
	getNamedItem: function() { ... },
	removeNamedItem: function() { ... }, /* 通过 索引值 */
	setNamedItem: function() { ... },
	item: function(pos) { ... }
}	
			

removeNamedItemNS(),getNamedItemNS(),setNamedItemNS()是XML DOM方法,我们就不用管他了

  • index:返回attr节点,根据索引值
  • key:返回attr节点,根据nodeName,建议采用 key 而不是index,因为节点顺序不是按照html节点先后顺序。
  • length:属性的个数,只读
  • item:返回索引为 pos 的attr节点
    console.log(btn.attributes.item(0).nodeName) // value
    console.log(btn.attributes.item(0).nodeValue) // 123
    				
  • removeNamedItem:移除节点,以节点的 nodeName 为索引。跟removeAttribute()不同的是它会返回被删除属性的attr节点
    console.log( buttons[0].removeAttribute('value') ) //undefinded
    console.log( buttons[0].attributes.removeNamedItem('value') ) // value="123"
    				
  • setNamedItem:添加节点,以节点的 nodeName 为索引。跟setAttribute()一样,但是操作却要多上好几步
    var namedItem = document.createAttribute("value"); //首先创建属性节点
    namedItem.value = "This is a ToolTip"; // 接着设置属性值
    buttons[0].attributes.setNamedItem(namedItem);	//最后将set属性节点
    // 等同于
    buttons[0].setAttribute('value','This is a ToolTip');
    					
  • getNamedItem:返回 nodeName 属性等于 nodeName 的节点。返回结果跟第一种方法类似
    console.log(elem1.attributes.getNamedItem('id').nodeValue) // attr节点 值
    console.log(elem1.attributes['id'].nodeName)	// attr节点 名
    console.log(elem1.getAttribute('id')) // 属性的值	
    					

了解了以上知识,有些人应该知道怎么获取button的value,代码就不贴了。

虽然attributes()比以下要讲的三个方法麻烦,但是兼容性比其好。

setAttribute()、getAttribute()、removeAttribute()兼容性。

IE6/7中setAttribute()、getAttribute()不能操作class、for等属性。如下代码

<label>label:</label><input type="text" id="test"/>
<script>
	var lab = document.getElementsByTagName('label')[0];
	lab.setAttribute('class', '123'); 
	lab.setAttribute('for', 'test');
</script>
	

setAttribute()兼容方法:

修改属性拼写,如下表:

  1. tabindex → tabIndex
  2. readonly → readOnly
  3. for → htmlFor
  4. class → className
  5. maxlength → maxLength
  6. cellspacing → cellSpacing
  7. cellpadding → cellPadding
  8. rowspan → rowSpan
  9. colspan → colSpan
  10. usemap → useMap
  11. frameborder → frameBorder
  12. contenteditable → contentEditable

最终方案:

  • 不支持的属性按照以上列表修改

    <label id="label" for="">1</label>
    <input type="radio" name="" id="radio1">
    <script>
    	var elLabel = document.getElementById('label');
    	elLabel.setAttribute('for','radio1');
    	elLabel.setAttribute('htmlFor','radio1');
    </script>
    
  • 可以使用 attributes().setNamedItem()方法,缺点:步骤多,代码上文寻找

getAttribute()兼容方法

  • 跟getAttribute()方法1那样子修改
  • 使用 attributes.getNamedItem(‘rowspan’).nodeValue
    			alert(elLabel.attributes.getNamedItem('rowspan').nodeValue);
    			alert(elLabel.attributes['rowspan'].nodeValue);
    		

removeAttribute()也有跟跟getAttribute()和setAttribute()一样的问题,解决方案类似。这就就不说了

但是利用 attributes 对象不能解决操作 style

然后在这个页面我们可以看到IE6、7 是 不完全支持 这三个方法的。

我们自己写小工具的话操作 属性节点 跟 style 的话最好各自写方法。俗话说:让专业的来。

何时用attribute何时用property

attribute()和property()在IE9以上浏览器关系 跟 jQuery中 attr() 和 prop() 类似。测试代码如下:

<input type="checkbox" />
<input type="checkbox" checked/>
<input type="checkbox" checked="true"/>
<script>
    var inputs = document.getElementsByTagName('input');
    for ( var i = 0;i < inputs.length;i++){
        alert( inputs[i].getAttribute('checked') );
        alert( inputs[i]['checked'] );
    }
</script>
		

测试以上代码得出一下结果:

  1. IE6/7:false false true true true true
  2. IE8 : 空 false checked true checked true
  3. IE9/10/Firefox/Safari/Chrome/Opera :null false 空 true true true

结论:

  • 原生js中要判断checkbox/radio最终有没有选定,使用property而不要使用attribute,html代码中节点属性以及节点值都得制定。默认值最简便的方法就是保存在一个变量里;
  • 而在 jQuery中修复了此问题。所以 具有 true 和 false 两个属性的属性,如 checked, selected 或者 disabled 使用prop(),其他则使用 attr()。

本文源链接:http://www.html5jscss.com/property-attribute.html

转载请注明《JavaScript欲速则不达——属性节点》| html5jscss

评论关闭了.