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

时间:2022-09-05 13:20:12

关于钩子: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修改元素的属性

<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
<meta http-equiv="Content-Type" content="text/html; charset=gb2312" />
<!-----------------------------测试代码开始-------------------------------->
<span id="test" for="mmm" in="nnn" disabled='disabled' class='ccc'>测试属性修改</span></br></br>

<span id="preserve1c71f7f89c0a405a87f520f3fe275bf0" class="wlWriterPreserve"><script type="text/javascript">

var test = document.getElementById('test');

document.write('原始class值结果class='+ test.className + '</br>')

test.class = 1111;
document.write('通过class修为1111结果class=' + test.className+ '</br>')

test.className = 2222;
document.write('通过className修为2222结果class=' + test.className+ '</br>')
</script></span>
<!-----------------------------测试结束-------------------------------------->
</body>
</html>

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, selecttextarea等,

什么是元素的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 属性篇的更多相关文章

  1. web前端~~浏览器兼容问题(百度)

    所谓的浏览器兼容性问题,是指因为不同的浏览器对同一段代码有不同的解析,造成页面显示效果不统一的情况.在大多数情况下,我们的需求是,无论用户用什么浏览器来查看我们的网站或者登陆我们的系统,都应该是统一的 ...

  2. WEB前端开发人员须知的常见浏览器兼容问题及解决技巧

    所谓的浏览器兼容性问题,是指因为不同的浏览器对同一段代码有不同的解析,造成页面显示效果不统一的情况.在大多数情况下,我们的需求是,无论用户用什么浏览器来查看我们的网站或者登陆我们的系统,都应该是统一的 ...

  3. 浅谈Web前端浏览器兼容问题

    对于兼容最近一直困扰我,以前写的代码只是针对高质量用户来使用 不考虑IE7,8 这样的浏览器 ,但是最近我开发的时候必须要兼容,大喊一声我曹,没有办法,自己来吧! 所谓的浏览器兼容性问题,是指因为不同 ...

  4. jQuery-1&period;9&period;1源码分析系列(七) 钩子(hooks)机制及浏览器兼容

    处理浏览器兼容问题实际上不是jQuery的精髓,毕竟让技术员想方设法取弥补浏览器的过错从而使得代码乱七八糟不是个好事.一些特殊情况的处理,完全实在浪费浏览器的性能:突兀的兼容解决使得的代码看起来既不美 ...

  5. 【jquery】基于 jquery 实现 ie 浏览器兼容 placeholder 效果

    placeholder 是 html5 新增加的属性,主要提供一种提示(hint),用于描述输入域所期待的值.该提示会在输入字段为空时显示,并会在字段获得焦点时消失.placeholder 属性适用于 ...

  6. jQuery实现ie浏览器兼容placeholder效果

    <!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8&quo ...

  7. CSS3与页面布局学习总结(八)——浏览器兼容与前端性能优化

    一.浏览器兼容 1.1.概要 世界上没有任何一个浏览器是一样的,同样的代码在不一样的浏览器上运行就存在兼容性问题.不同浏览器其内核亦不尽相同,相同内核的版本不同,相同版本的内核浏览器品牌不一样,各种运 ...

  8. 细数Qt开发的各种坑&lpar;欢迎围观&rpar;

    1:Qt的版本多到你数都数不清,多到你开始怀疑人生.从4.6开始到5.8,从MSVC编译器到MINGW编译器,从32位到64位,从Windows到Linux到MAC.MSVC版本还必须安装对应的VS2 ...

  9. Vue(SPA) WebPack模块化打包、SEO优化(Vue SSR服务端同构直出)、全浏览器兼容完整解决方案

    白驹过隙,时光荏苒 大概去年这个时候写了angular 结合webpack的一套前端方案,今年此时祭出vue2结合webpack的一套前端方案. 明年的这个时候我又是在做什么... 读在最前面: 1. ...

随机推荐

  1. 0x80040E14 Caused by Max Url Length bug

    We get a case when the customer access a SharePoint site, he meet an error on SharePoint. 0x80040E14 ...

  2. 用node搭建静态文件服务器

    占个坑,写个node静态文件服务器

  3. Linux 下的dd命令使用详解&lpar;摘录&rpar;

    一.dd命令的解释 dd:用指定大小的块拷贝一个文件,并在拷贝的同时进行指定的转换. 注意:指定数字的地*以下列字符结尾,则乘以相应的数字:b=512:c=1:k=1024:w=2 参数注释: 1. ...

  4. git 换行符LF与CRLF转换问题

    git 换行符LF与CRLF转换问题 一.背景 在各操作系统下,文本文件所使用的换行符是不一样的.UNIX/Linux 使用的是 0x0A(LF),早期的 Mac OS 使用的是0x0D(CR),后来 ...

  5. A&ast;啦啦啦

    ...A*是个啥都不知道.. 大家注意K短路可能不存在!!!! 果然是s==t的问题……加个if(s==t) k++就A了…… 单用Dij,tle到死 原来是单向k短路........开始以为是双向的 ...

  6. 集合工具类 - CollectionUtil&period;java

    集合工具类,提供数组转LIST.数组转SET.合并集合.计算笛卡儿积等方法. 源码如下:(点击下载 -  CollectionUtil.java.ArrayUtil.java.commons-lang ...

  7. 原生ajax详解

    Ajxa局部刷新用于提高用户体验.Ajax技术的核心是XMLHttpRequest对象(简称XHR) XMLHttpRequest对象 XMLHttpRequest对象在ie7及更高版本可以这样申明. ...

  8. TCP&sol;IP NAT知识梳理

    一. IP地址的获取 首先,互联网上的每台主机都有一个唯一的IP地址标识,计算机在通信时需要向网络中的DHCP(动态主机配置协议)服务器申请一个IP地址,但开始主机并不知道哪台机器是DHCP服务器(不 ...

  9. node-js:文摘

    ES6相关 1.module.exports与exports,export与export default之间的关系和区别 nodejs基础 1.NodeJs安装与全局配置(不建议修改包的全局安装路径, ...

  10. LINQ基本概念及误区

    LINQ基本概念: LINQ全名Language Integrated Query(语言集成查询),它允许我们通过C#(或VB)语言,以操作内存数据的方式,查询数据库. LINQ的由来: 传统上,对数 ...