jquery源码解析:val方法和valHooks对象详解
这一课,我们将讲解val方法,以及对value属性的兼容性处理,jQuery中通过valHooks对象来处理。
首先,我们先来看下val方法的使用:
$("#input1").val() //获取input元素的value属性值
$("#input1").val("hello") //设置input元素的value属性值为hello。
然后我们来看一下val方法的源码:
jQuery.fn.extend({
......
val: function( value ) {
var hooks, ret, isFunction,
elem = this[0];
if ( !arguments.length ) { //如果是获取操作,也就是参数为0时.
if ( elem ) {
hooks = jQuery.valHooks[ elem.type ] || jQuery.valHooks[ elem.nodeName.toLowerCase() ];
//valHooks有以下几个属性对象:option(下拉框的子选项),select(下拉框),radio(单选按钮),checkbox(复选按钮)。也就意味着需要对这四种元素进行兼容性处理。其中radio的type=radio,checkbox的type=checkbox,select的type,默认为select-one(单选),还可以设置成select-multiple(<select multiple><option></option></select>,多选)。
if ( hooks && "get" in hooks && (ret = hooks.get( elem, "value" )) !== undefined ) {
return ret;
}
ret = elem.value;
return typeof ret === "string" ? ret.replace(rreturn, "") : ret == null ? "" : ret;
}
return;
}
isFunction = jQuery.isFunction( value );
return this.each(function( i ) { //设置操作,是针对每个元素
var val;
if ( this.nodeType !== 1 ) { //必须是元素节点
return;
}
if ( isFunction ) {
val = value.call( this, i, jQuery( this ).val() );
} else {
val = value;
}
if ( val == null ) { //针对这种情况:$("input").val(null);
val = "";
} else if ( typeof val === "number" ) { //如果传入的是数字类型,就转换成字符串
val += "";
} else if ( jQuery.isArray( val ) ) { //这里是针对checkbox,radio这种元素的,比如:$("#input2").val(["hello"]);这里如果传入的是字符串的话,是对checkbox的value属性赋值,但是传入数组,就代表checkbox的value是否等于hello,如果等于,就被选择上,如果不等于就不被选择上。
val = jQuery.map(val, function ( value ) {
return value == null ? "" : value + "";
});
}
hooks = jQuery.valHooks[ this.type ] || jQuery.valHooks[ this.nodeName.toLowerCase() ];
if ( !hooks || !("set" in hooks) || hooks.set( this, val, "value" ) === undefined ) { //请看下面的代码解释
this.value = val;
}
});
}
});
jQuery.extend({
valHooks: {
option: { //当你获取option元素的value属性值时,如果没有对此option显式设置value值,获取到的值是option的text,也就是option的文本。但是IE6-7下获取到的值是""。
get: function( elem ) {
var val = elem.attributes.value; //在IE6-7下,val是一个object。
return val.specified ? elem.value : elem.text;//如果val.specified为true,就代表value被显式设置了,因此直接返回elem.value,如果为false,就代表没有显式设置,因此返回elem.text。
}
},
select: {
get: function( elem ) { //当select是单选时,获取的value值,就是你选择的那个option的值,如果是多选,获取值时,就是你选择的所有option的值的数组形式。
var value, option,
options = elem.options, //select的所有option的集合。
index = elem.selectedIndex, //当前选择的option的索引值
one = elem.type === "select-one" || index < 0,
values = one ? null : [], //如果是单选,values=null,如果是多选,values=[]。
max = one ? index + 1 : options.length,
i = index < 0 ? max : one ? index : 0;
for ( ; i < max; i++ ) { //单选,循环一次,多选,循环多次
option = options[ i ];
if ( ( option.selected || i === index ) && //IE6-9下,点击reset按钮时,option的selected不会恢复默认值,其他浏览器会恢复所有option的selected的默认值。
( jQuery.support.optDisabled ? !option.disabled : option.getAttribute("disabled") === null ) && //如果option被设置了disabled,那么获取option的值时,是获取不到的。
( !option.parentNode.disabled || !jQuery.nodeName( option.parentNode, "optgroup" ) ) ) { //如果option的父元素被设置了disabled,并且父元素是optgroup,那么也获取不到。
value = jQuery( option ).val();
if ( one ) {
return value;
}
values.push( value );
}
}
return values;
},
set: function( elem, value ) {
var optionSet, option,
options = elem.options,
values = jQuery.makeArray( value ), //把value转换成数组
i = options.length;
while ( i-- ) {
option = options[ i ];
if ( (option.selected = jQuery.inArray( jQuery(option).val(), values ) >= 0) ) { //判断select的子元素option的value是否在values数组中,如果在,就会把这个option选中。
optionSet = true;
}
}
if ( !optionSet ) {
elem.selectedIndex = -1; //如果select下的option的value值没有一个等于value的,那么就让select的选择索引值赋为-1.让select框中没有任何值。
}
return values;
}
}
}
})
jQuery.each([ "radio", "checkbox" ], function() {
jQuery.valHooks[ this ] = {
set: function( elem, value ) {
if ( jQuery.isArray( value ) ) { //当value是数组时,看此元素的value值是否在数组value中,如果在就让元素被选择上。此元素只有radio,checkbox这两种。
return ( elem.checked = jQuery.inArray( jQuery(elem).val(), value ) >= 0 );
}
}
};
if ( !jQuery.support.checkOn ) { //如果元素是radio或者checkbox,我们去获取它的默认value值时,老版本webkit得到的值是"",而其他浏览器是on,因此当没有对此元素显式设置它的value值时(通过getAttribute获取的value的是null),我们通过input.value获取它的默认值,所有浏览器都返回on。
jQuery.valHooks[ this ].get = function( elem ) {
return elem.getAttribute("value") === null ? "on" : elem.value;
};
}
});
兼容处理,在jQuery中叫做hooks。针对不同的兼容处理,有不同的hooks来处理。比如:value值,就有valHooks,属性值,就有attrHooks,propHooks等。
加油!
jquery源码解析:val方法和valHooks对象详解的更多相关文章
- jQuery 源码解析(三十) 动画模块 $.animate()详解
jQuery的动画模块提供了包括隐藏显示动画.渐显渐隐动画.滑入划出动画,同时还支持构造复杂自定义动画,动画模块用到了之前讲解过的很多其它很多模块,例如队列.事件等等, $.animate()的用法如 ...
- jQuery 源码分析(十九) DOM遍历模块详解
jQuery的DOM遍历模块对DOM模型的原生属性parentNode.childNodes.firstChild.lastChild.previousSibling.nextSibling进行了封装 ...
- jQuery 源码分析(十) 数据缓存模块 data详解
jQuery的数据缓存模块以一种安全的方式为DOM元素附加任意类型的数据,避免了在JavaScript对象和DOM元素之间出现循环引用,以及由此而导致的内存泄漏. 数据缓存模块为DOM元素和JavaS ...
- jQuery源码分析(九) 异步队列模块 Deferred 详解
deferred对象就是jQuery的回调函数解决方案,它解决了如何处理耗时操作的问题,比如一些Ajax操作,动画操作等.(P.s:紧跟上一节:https://www.cnblogs.com/grea ...
- jquery源码解析:代码结构分析
本系列是针对jquery2.0.3版本进行的讲解.此版本不支持IE8及以下版本. (function(){ (21, 94) 定义了一些变量和函数, jQuery = function() ...
- JQuery源码解析(一)
写在前面:本<JQuery源码解析>系列是基于一些前辈们的文章进行进一步的分析.细化.修改而写出来的,在这边感谢那些慷慨提供科普文档的技术大拿们. 要查阅JQ的源文件请下载开发版的JQ.j ...
- jQuery 源码解析二:jQuery.fn.extend=jQuery.extend 方法探究
终于动笔开始 jQuery 源码解析第二篇,写文章还真是有难度,要把自已懂的表述清楚,要让别人听懂真的不是一见易事. 在 jQuery 源码解析一:jQuery 类库整体架构设计解析 一文,大致描述了 ...
- equals()方法和hashCode()方法详解
equals()方法和hashCode()方法详解 1. Object类中equals()方法源代码如下所示: /** * Object类中的equals()方法 */ public boolean ...
- ASP.NET MVC 5 学习教程:Edit方法和Edit视图详解
原文 ASP.NET MVC 5 学习教程:Edit方法和Edit视图详解 起飞网 ASP.NET MVC 5 学习教程目录: 添加控制器 添加视图 修改视图和布局页 控制器传递数据给视图 添加模型 ...
随机推荐
- 新手C#int.Parse、int.TryParse的学习2018.08.04
int.Parse()用于将字符串转换为32为int类型,但是在遇到非数字或者类似1.545这种小数的时候会报错,后来采用了int.TryParse,这个在转换后会判断是否可以正常转换,若不能,会返回 ...
- mybatis使用foreach进行批量插入和删除操作
一.批量插入 1.mapper层 int insertBatchRoleUser(@Param("lists") List<RoleUser> lists);//@Pa ...
- Gcc对头文件与库文件的搜索路径
一.简介 对头文件与库文件的搜索路径不太清楚,编译.运行时老碰到问题,ldd查看程序的链接时,总是出现unkown链接. 二.头文件 gcc 在编译时寻找所需要的头文件 : 1)搜寻会从-I开始 2) ...
- DataStage 七、在DS中使用配置文件分配资源
DataStage序列文章 DataStage 一.安装 DataStage 二.InfoSphere Information Server进程的启动和停止 DataStage 三.配置ODBC Da ...
- 微信小程序进行地图导航使用地图功能
之前我写过的文章当中,提过小程序的打包大小.所以特地去下载一个区域的地图的这种方法,是不存在的. 我用的导航主要使用的是应用外的导航,这篇文章可能对于非常熟悉小程序的小伙伴来说就是小case,所以只适 ...
- 分布式事务,EventBus 解决方案:CAP【中文文档】(转)
出处:http://www.cnblogs.com/savorboard/p/cap-document.html 前言 很多同学想对CAP的机制以及用法等想有一个详细的了解,所以花了将近两周时间写了这 ...
- 苹果禁用UUID了,咋办?
By now you have probably heard that Apple is deprecating support for attaining a UDID from an iOS de ...
- Google Tango初学者教程
Getting Started with the Tango Java API In this tutorial, we'll go through setting up your build env ...
- struts2 动态Action
1.java 2.struts.xml struts2.5,默认关闭动态Action,着色的是开启和使用动态action 3.JSP 小结:访问时,用!后跟方法名的方法,方法返回值----->r ...
- 面试经验之——HE集团,YZ科技
上周去了HE集团面试,该集团是做车辆辅助驾驶系统的,最终目标瞄准的是自动驾驶,加上再之前在YZ科技的面试经验,有些关于车辆驾驶上的心得想聊聊. 首先说说两个企业的面试情况吧.YZ科技中的两个技术聊天都 ...