zoukankan      html  css  js  c++  java
  • 深入浏览器兼容 细数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  中的对象

    image

    源码部分

    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, 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的处理

    option,select

    对于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匹配对应的钩子处理方法

    image

    节点属性的差异对比:

    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;
                };
            }
        });
  • 相关阅读:
    趣题:寻找出现了奇数次的数
    zstu2016校赛圣杯战争
    HDU 5183 Negative and Positive (NP) ——(后缀和+手写hash表)
    HDU 5673 Robot ——(卡特兰数)
    HDU 3775 Chain Code ——(Pick定理)
    2016 ICPC北京站现场赛总结(再度流水账)
    2014苏州大学新生赛第二场(12.10)题目解析
    【Jump Game II 】cpp
    【Jump Game】cpp
    【 Sqrt(x) 】cpp
  • 原文地址:https://www.cnblogs.com/aaronjs/p/3434830.html
Copyright © 2011-2022 走看看