jQuery源码阅读8-2:属性操作val(),removeAttr() Posted on 2014-05-20 | In jQuery源码阅读 | 属性操作是比较独立的一块,这次说下prop相关的, 和属性必须用的access 下次说更麻烦一点的attr,val 还有css相关的 以prop的一次操作为例, 调用顺序是: fn.prop -> access -> jQuery.prop 12345678910111213141516171819202122232425262728293031323334353637383940core_rspace = /\s+/,//匹配一些列空格// Test setAttribute on camelCase class. If it works, we need attrFixes when doing get/setAttribute (ie6/7)getSetAttribute: div.className !== "t",removeAttr: function( elem, value ) { var propName, attrNames, name, isBool, i = 0; //nodeType === 1代表elem是普通dom元素 if ( value && elem.nodeType === 1 ) { //按空格切分成数组 attrNames = value.split( core_rspace ); //处理elem一次传入多个值 for ( ; i < attrNames.length; i++ ) { name = attrNames[ i ]; if ( name ) { //修复名称 propName = jQuery.propFix[ name ] || name; //是否在布尔参数的列表里 isBool = rboolean.test( name ); // See #9699 for explanation of this approach (setting first, then removal) // Do not do this for boolean attributes (see #10870) //不是布尔的, 写入"" if ( !isBool ) { jQuery.attr( elem, name, "" ); } //因为兼容问题,先写入空, 再removeAttribute, 这个getSetAttribute检测div.className是否等于t elem.removeAttribute( getSetAttribute ? name : propName ); // Set corresponding property to false for boolean attributes //布尔型的写入false if ( isBool && propName in elem ) { elem[ propName ] = false; } } } }}, 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131rreturn = /\r/g,//匹配回车val: function( value ) { var hooks, ret, isFunction, elem = this[0];//目标元素 //无参数, 读取 if ( !arguments.length ) { if ( elem ) { //这的钩子针对option和select hooks = jQuery.valHooks[ elem.type ] || jQuery.valHooks[ elem.nodeName.toLowerCase() ]; //产生钩子了,就调用钩子 if ( hooks && "get" in hooks && (ret = hooks.get( elem, "value" )) !== undefined ) { return ret; } ret = elem.value; return typeof ret === "string" ? //结果是string, 把回车去掉 ret.replace(rreturn, "") : //数字直接返回, undefined和null返回"" ret == null ? "" : ret; } return; } //value接收的是否是函数 isFunction = jQuery.isFunction( value ); //有参数,写入模式 return this.each(function( i ) { var val, self = jQuery(this);//这个this是当前遍历的dom元素 //nodeType必须是普通dom if ( this.nodeType !== 1 ) { return; } if ( isFunction ) { //传入函数.call( 当前dom, idx , 当前dom的.val()值 ) val = value.call( this, i, self.val() ); } else { //val先等于value待处理 val = value; } //undefined和null处理成"", 数组处理为string , if ( val == null ) { val = ""; } else if ( typeof val === "number" ) { val += ""; } else if ( jQuery.isArray( val ) ) { //利用map转成字串数组 val = jQuery.map(val, function ( value ) { return value == null ? "" : value + ""; }); } //特殊处理select的set的钩子 hooks = jQuery.valHooks[ this.type ] || jQuery.valHooks[ this.nodeName.toLowerCase() ]; //钩子里有set则使用钩子写入 if ( !hooks || !("set" in hooks) || hooks.set( this, val, "value" ) === undefined ) { this.value = val; } }); }}); jQuery.extend({ valHooks: { option: { get: function( elem ) { //兼容读取elem.attributes.value var val = elem.attributes.value; return !val || val.specified ? elem.value : elem.text; } }, select: { get: function( elem ) { var value, option, options = elem.options,//数组 index = elem.selectedIndex,//选中序号 one = elem.type === "select-one" || index < 0,//是否是单选 values = one ? null : [],//缓存结果 max = one ? index + 1 : options.length, i = index < 0 ? max : one ? index : 0; //遍历所有options for ( ; i < max; i++ ) { option = options[ i ]; //一堆兼容处理 if ( ( option.selected || i === index ) && // Don't return options that are disabled or in a disabled optgroup ( jQuery.support.optDisabled ? !option.disabled : option.getAttribute("disabled") === null ) && ( !option.parentNode.disabled || !jQuery.nodeName( option.parentNode, "optgroup" ) ) ) { // Get the specific value for the option value = jQuery( option ).val(); //单选就一个 if ( one ) { return value; } //多选加入数组 values.push( value ); } } return values; }, set: function( elem, value ) { //整理成参数数组 var values = jQuery.makeArray( value ); //找子元素, jQuery(elem).find("option").each(function() { //出现在values数组的就选上 this.selected = jQuery.inArray( jQuery(this).val(), values ) >= 0; }); //如果values没值,selectedIndex做处理 if ( !values.length ) { elem.selectedIndex = -1; } return values; } } },