教程集 www.jiaochengji.com
教程集 >  jQuery  >  jquery 教程  >  正文 深入浏览器兼容 细数jQuery Hooks 属性篇

深入浏览器兼容 细数jQuery Hooks 属性篇

发布时间:2016-09-07   编辑:jiaochengji.com
教程集为您提供深入浏览器兼容 细数jQuery Hooks 属性篇等资源,欢迎您收藏本站,我们将为您提供最新的深入浏览器兼容 细数jQuery Hooks 属性篇资源

关于钩子:http://www.cnblogs.com/aaronjs/p/3387906.html

本章的目的很简单,通过钩子函数更细节的了解浏览器差异与处理方案,

版本是2.0.3所以不兼容ie6.7.8,所以对应了钩子会少很多。。

总的来说钩子在.attr(), .prop(), .val() and .css() 四种操作中会涉及

 

属性操作的钩子

propFix

propHooks

attrHooks

valHooks

 


jquery.propFix  中的对象

深入浏览器兼容 细数jQuery Hooks 属性篇

 

源码部分

1:保留值属性名字修正

jQuery.propFix: {     for   :  "htmlFor",    class  :  "className" },

  • 由于class属于JavaScript保留值,因此当我们要操作元素的class属性值时,直接使用obj.getAttribute(‘class’)和obj.setAttribute(‘class’, ‘value’)可能会遭遇浏览器兼容性问题,W3C DOM标准为每个节点提供了一个可读写的className属性,作为节点class属性的映射,标准浏览器的都提供了这一属性的支持,因此,可以使用e.className访问元素的class属性值,也可对该属性进行重新斌值。而IE和Opera中也可使用e.getAttribute(‘className’)和e.setAttribute(‘className’, ‘value’)访问及修改class属性值。相比之下,e.className是W3C DOM标准,仍然是兼容性最强的解决办法。
  • 同理htmlFor用于读取label标签的for属性

 

测试demo,通过class与className修改元素的属性


 

 

2:与表单操作相关:

反转下,让钩子适配用伪代码匹配,目测应该是为了兼容开发者输入大小写格式不正确

比如输入错误格式:cellpadding

如果jQuery.propFix 转成cellPadding ,驼峰写法了

jQuery.each([         "tabIndex",         "readOnly",         "maxLength",         "cellSpacing",         "cellPadding",         "rowSpan",         "colSpan",         "useMap",         "frameBorder",         "contentEditable"     ], function() {         jQuery.propFix[ this.toLowerCase() ] = this;     });

tabIndex 属性可设置或返回按钮的 tab 键控制次序

readonly 属性规定输入字段为只读。

maxlength 属性规定输入字段的最大长度,以字符个数计。

cellspacing 属性规定单元格之间的空间

cellpadding 属性规定单元边沿与其内容之间的空白。

rowspan 属性规定单元格可横跨的行数。

colspan 属性规定单元格可横跨的列数。

 

HTML <img> 标签的

usemap 属性将图像定义为客户端图像映射

frameBorder 属性设置或返回是否显示框架周围的边框。

contenteditable 属性规定是否可编辑元素的内容。

 

值得一提的是这个方法用的比较巧妙了,收集所有的合集名,然后在每一个上下文回调中把每一个名字传递到propFix方法,key转成小写,value保存正确写法

jQuery.propFix[ this.toLowerCase() ] = this;

 


jQuery.propHooks 属性方法

关于tabIndex属性

http://www.w3help.org/zh-cn/causes/SD2021

propHooks: {     tabIndex: {         get: function( elem ) {             return elem.hasAttribute( "tabindex" ) || rfocusable.test( elem.nodeName ) || elem.href ?                 elem.tabIndex :                 -1;         }     } }

 

// Support: IE9+ // Selectedness for an option in an optgroup can be inaccurate if ( !jQuery.support.optSelected ) {     jQuery.propHooks.selected = {         get: function( elem ) {             var parent = elem.parentNode;             if ( parent && parent.parentNode ) {                 parent.parentNode.selectedIndex;             }             return null;         }     }; }

 


jQuery.attrHooks 方法

attrHooks: {     type: {         set: function( elem, value ) {             if ( !jQuery.support.radioValue && value === "radio" && jQuery.nodeName(elem, "input") ) {                 // Setting the type on a radio button after the value resets the value in IE6-9                 // Reset value to default in case type is set after value during creation                 var val = elem.value;                 elem.setAttribute( "type", value );                 if ( val ) {                     elem.value = val;                 }                 return value;             }         }     } },

 


jQuery.valHooks 方法

根据 JQuery api文档 的描述,.val() 函数有两种用法,分别用来获取或设置元素的值,这里只介绍获取值的方法。

文档里面说 .val 主要是用于获取元素的value,比如 input, select 和 textarea等,

什么是元素的value?”

select 标签为例,如下的代码:

测试代码

<select id="choise">   <option value="1">One</option>   <option value="2">Two</option>   <option value="3">Three</option>   <option value="4">Four</option> </select>

这里的option有2个值,一个是value = 1 另一个则是 text = One

option 真正的 value 应该是其 value 属性中的值,而不是 option 标签中间所包含的内容

在 w3school 的文档中对 optionvalue 属性的做了如下定义:

The value attribute specifies the value to be sent to a server when a form is submitted. The content between the opening <option> and closing </option> tags is what the browsers will display in a drop-down list. However, the value of the value attribute is what will be sent to the server when a form is submitted. Note: If the value attribute is not specified, the content will be passed as the value instead.

这一点对于所有可以拥有 value 属性的标签都是相同的,即在对一个元素调用 .val() 函数时,首先取其 value 属性的值,如果没有的话,再使用其 text 值。

 

那么接下来就要引入我们的valHooks,针对option,select的处理

深入浏览器兼容 细数jQuery Hooks 属性篇深入浏览器兼容 细数jQuery Hooks 属性篇
option,select        valHooks: {             option: {                 get: function( elem ) {                     // attributes.value is undefined in Blackberry 4.7 but                     // uses .value. See #6932                     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;                      // Loop through all the selected options                     for ( ; i < max; i++ ) {                         option = options[ i ];                          // IE6-9 doesn't update selected after form reset (#2551)                         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();                              // We don't need an array for one selects                             if ( one ) {                                 return value;                             }                              // Multi-Selects return an array                             values.push( value );                         }                     }                      return values;                 },                  set: function( elem, value ) {                     var optionSet, option,                         options = elem.options,                         values = jQuery.makeArray( value ),                         i = options.length;                      while ( i-- ) {                         option = options[ i ];                         if ( (option.selected = jQuery.inArray( jQuery(option).val(), values ) >= 0) ) {                             optionSet = true;                         }                     }                      // force browsers to behave consistently when non-matching value is set                     if ( !optionSet ) {                         elem.selectedIndex = -1;                     }                     return values;                 }             }         },

对于val方法的取值部分

if ( elem ) {     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" ?         // handle most common string cases         ret.replace(rreturn, "") :         // handle cases where value is null/undef or number         ret == null ? "" : ret; }

通过jQuery.valHooks匹配对应的钩子处理方法

深入浏览器兼容 细数jQuery Hooks 属性篇

 

节点属性的差异对比:

select : 创建单选或多选菜单

  1. type:”select-one”
  2. tagName: “SELECT”
  3. value: “111”
  4. textContent: “↵ Single↵ Single2↵”

option : 元素定义下拉列表中的一个选项

  1. tagName: “OPTION”
  2. value: “111”
  3. text: “Single”
  4. textContent: “Single”

radio : 表单中的单选按钮

  1. type: “radio”
  2. value: “11111”

checkbox : 选择框

  1. type: “checkbox”
  2. value: “11111”

 

根据对比select的节点type是’select-one’与其余几个还不同,所以jQuery在适配的时候采用优先查找type,否则就找nodeName的策略

hooks = jQuery.valHooks[ elem.type ] || jQuery.valHooks[ elem.nodeName.toLowerCase() ];

 

如果钩子匹配到了,并且还存在get方法,那么就要调用这个方法了,如果有返回值就返回当前的这个最终值

if ( hooks && "get" in hooks && (ret = hooks.get( elem, "value" )) !== undefined ) {     return ret; }

 

那么具体的兼容问题就会跑到对应的钩子方法中处理了

// Loop through all the selected options                     for ( ; i < max; i++ ) {                         option = options[ i ];                          // IE6-9 doesn't update selected after form reset (#2551)                         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();                              // We don't need an array for one selects                             if ( one ) {                                 return value;                             }                              // Multi-Selects return an array                             values.push( value );                         }                     }

通过selectedIndex 属性可设置或返回下拉列表中被选选项的索引号

通过递归select中的所有option

在包装jQuery( option ).val()

从而调用option的钩子方法get ,

get: function( elem ) {                     // attributes.value is undefined in Blackberry 4.7 but                     // uses .value. See #6932                     var val = elem.attributes.value;                     return !val || val.specified ? elem.value : elem.text;                 }

elem.attributes.value返回对应的option的val值

所以这里就兼容的默认返回val,否则就返回text的内容了

 


radio,checkbox

// Radios and checkboxes getter/setter     jQuery.each([ "radio", "checkbox" ], function() {         jQuery.valHooks[ this ] = {             set: function( elem, value ) {                 if ( jQuery.isArray( value ) ) {                     return ( elem.checked = jQuery.inArray( jQuery(elem).val(), value ) >= 0 );                 }             }         };         if ( !jQuery.support.checkOn ) {             jQuery.valHooks[ this ].get = function( elem ) {                 // Support: Webkit                 // "" is returned instead of "on" if a value isn't specified                 return elem.getAttribute("value") === null ? "on" : elem.value;             };         }     });

您可能感兴趣的文章:
深入浏览器兼容 细数jQuery Hooks 属性篇
jQuery源码分析系列
jQuery 2.0.3 源码分析 钩子机制 – 属性操作
解密jQuery内核 样式操作
解密jQuery内核 DOM操作方法(二)html,text,val
JQuery从头学起第一讲
jQuery(1.6.3) 中css方法对浮动的实现缺陷分析
jquery和ajax的关系详细介绍
下拉列表选择项的选中在不同浏览器中的兼容性问题探讨
JavaScript MVC 学习笔记(四)类的使用(下)

[关闭]
~ ~