不要使用元素的value存取数据

元素value的一些问题

元素的value属性在不同的浏览器存在着不同的问题。

问题1:li元素的value会被自动赋值

<ul>
	<li id="test" value></li>
	<li id="test1" value=""></li>
</ul>
<script>
	alert($('#test').attr('value'));// IE8及以下:1
	alert($('#test')[0].value);// IE8及以下:1
	alert($('#test1').attr('value'));// IE8及以下:1
</script>


你信不信,在IE下上面的结果确实是1!不管用你用什么方法获取到它的value属性,结果都是1.这是多么恐怖的一件事情,如果你的一个li刚好没有值,你却用这种方法来做某种判断甚至将它的数据上传服务器的时候,出错几乎是注定的。


问题2:若元素已经有value属性,使用jQuery的val()方法赋值不会改变value属性值

<input id="test" value=1 />
$('#test').val('2');
	
alert($('#test')[0].getAttribute('value'));// 1
alert($('#test').attr('value'));// 1
	
alert($('#test')[0].value);// 2
alert($('#test').val());// 2


我在项目中就遇到了这个问题。我要做一个将会议数据编辑的功能。于是我首先将已经有的数据以模板的方式进行渲染,比如有以下模板:
<input type="text" fieldName="meetingTime" value="<%=meetingTime%>" />
<div fieldName="meetingName" value="<%=meetingName%>"><%=meetingName%><span style="font-family: Arial, Helvetica, sans-serif;"></div></span>
$el.append(_.template(tpl)(data));


对其进行渲染后插入到DOM中,如果此时data的meetingTime属性有值(假设为10:00),然后用户又用时间选择器选择了一个新的时间(假设为12:00),此时时间选择器会用val()方法的方式对input元素进行赋值,此时input元素的显示值是12:00是正确的,页面中还有很多其他元素,于是为了统一取到值,我用$iput.attr('value')获取元素的值。此时,问题就出现了!对于input元素,我获取到的是其value的值而不是其真正被val()方法set的值!
其实,若是以value的方式来保存值,那么在设置值的时候用jQuery的attr('value',val)或者原生的setAttribute('value',val)都是可以的,只要获取的时候使用jQuery的attr('value')或者原生的getAttribute('value')都能正确获取值。就怕元素已有value属性值,又用jQuery的val方法来设置值,取值的时候又用了attr()或者getAttribute()来取值,就悲剧了。
其实,从上面的测试不难看出其原因。总结如下:

<input id="test" value=1 />
alert('value' in $('#test')[0]);// true

<div id="test1" value=1></div>
alert('value' in $('#test1')[0]);// false

1、如果元素有自带的value属性(一般是表单元素),如input,如果没有给input DOM对象通过jq的val()方法或者直接inputEl.value=1的方式为其设置value值,那么DOM对象的value值默认为DOM元素自带value属性的值;如果通过以上方式设置了值,元素显示的值会跟着改变,DOM对象的值会改变,但是元素的属性值还是原来的value值,即使原来没有值现在也不会有(原生为null,jq的attr('value')为undefined)。
2、如果元素没有自带的value属性,如div元素,如果元素的value属性有值,获取的DOM对象的value值并不存在(divEl.value或$(divEl).val()均为undefined)。为div DOM对象赋了值,元素的value属性的值也保持原来的值,不会受影响。
不好理解?其实从Javascript原型继承的角度来看问题就很清楚了。
假设原来带有value属性的DOM元素作为一个父类HTMLElement存在,我们获取一个DOM对象的时候就是获取了一个HTMLElement类的实例。实现可能如下:
function HTMLElment(){}
	HTMLElment.prototype = {
		name:null,
		value:null,
		getAttribute:function(attrName){
			return this[attrName];
		},
		setAttribute:function(attrName,attrVal){
			this[attrName] = attrVal;
		}
	};
	HTMLElment.prototype.setAttribute('value',1);
	var nodeObj = new HTMLElment();
	console.error(nodeObj.value);// 1
	
	nodeObj.value = 2;
	console.error(HTMLElment.prototype.value);//1
	console.error(nodeObj.value);//2
	
	HTMLElment.prototype.setAttribute('value',3);
	console.error(nodeObj.value);//2

原来不带有name、value属性的元素DOM对象则不会继承自类似HTMLElment的类,而是从其他类来实现。

解决方案

jQuery已经提供了获取数据的一个很好用的API,叫data()方法,使用如下:
<div id="test" data-value=1 ></div>
console.log($('#test').data('value'));// 1
$('#test').data({
<span style="white-space:pre">	</span>a:22
});
console.log($('#test').data());//{value: 1, a: 22}
没别的说的,用它就是了!准确无误,方便高效!
或者,使用统一的隐藏的input元素来设置值:
<input type="hidden" name="field1" value="" />

只是取值的时候记得统一用jq的val()或者元素对象.value来取值即可。
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 2
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值