jQ的html属性操作【后篇】
发布在# 菜鸟解读 jQuery #2014年5月27日view:4887
在文章任何区域双击击即可给文章添加【评注】!浮到评注点上可以查看详情。

承接上文,这里主要是介绍 attrHooks,nodeHook 的一系列修正操作

先来介绍nodeHook,这个主要是针对ie6,7低版本浏览器对于有些html属性不能正确的使用Attribute操作

if ( !getSetAttribute ) {
    fixSpecified = {
        name: true,
        id: true,
        coords: true
    };
    // ie67 对于某些html属性不能正确的设置和移除
    nodeHook = jQuery.valHooks.button = {
        get: function( elem, name ) {
            var ret;
            //取出属性节点
            ret = elem.getAttributeNode( name );
            // ( 节点存在 && ( name||id ? 节点值是否为空 : 节点是否被设置过 ) ) ? 节点值 : undefined ;
            // coords 是 图片热点区域的坐标属性,基本用不到
            return ret && ( fixSpecified[ name ] ? ret.nodeValue !== "" : ret.specified ) ?
                ret.nodeValue :
                undefined;
        },
        set: function( elem, value, name ) {
            // 获取属性节点
            var ret = elem.getAttributeNode( name );
            if ( !ret ) {
                //如果不存在 则创建然后设置到元素上
                ret = document.createAttribute( name );
                elem.setAttributeNode( ret );
            }
            //修改值
            return ( ret.nodeValue = value + "" );
        }
    };
}

来接续看attrHooks的修正,
attrHooks的修正代码比较零散,小编在这里整合在一起[源码中,间距较大]

jQuery.extend({
    attrHooks: {
        type: {
            set: function( elem, value ) {
                // ie9以下浏览器中 修改浏览器中有父元素的button,input元素的type属性,会报错
                if ( rtype.test( elem.nodeName ) && elem.parentNode ) {
                    jQuery.error( "type property can't be changed" );
                // ie低版本中 如果改变了input的type属性讲会丢失value的值,所以在修改前需要备份一份;
                }else if(!jQuery.support.radioValue&&value==="radio"&&jQuery.nodeName(elem,"input")){
                    var val = elem.value;
                    elem.setAttribute( "type", value );
                    if ( val ){
                        elem.value = val;
                    }
                    return value;
                }
            }
        },
        value: {
            get: function( elem, name ) {
                //ie6,7中在获取button的value属性时,返回的是dom的innerHTML的值,
                if ( nodeHook && jQuery.nodeName( elem, "button" ) ) {
                    //所以这里要改成从属性检点中获取
                    return nodeHook.get( elem, name );
                }
                //否则就正常返回dom的属性值即可
                return name in elem ?
                    elem.value :
                    null;
            },
            set: function( elem, value, name ) {
                if ( nodeHook && jQuery.nodeName( elem, "button" ) ) {
                    return nodeHook.set( elem, value, name );
                }
                elem.value = value;
            }
        }
    },
    propHooks: {
        tabIndex: {
            get: function( elem ) {
                //在获取tabindex属性时,tabIndex不总是返回正确的值,所以这里通过属性节点来进行值的获取
                var attributeNode = elem.getAttributeNode("tabindex");
                //属性节点存在 && 被设置过 ? 返回值 : 
                //rfocusable = /^(?:button|input|object|select|textarea)$/i 
                //rclickable = /^a(?:rea)?$/i
                return attributeNode && attributeNode.specified ?
                    parseInt( attributeNode.value, 10 ) :
                    rfocusable.test( elem.nodeName ) || rclickable.test( elem.nodeName ) && elem.href ?
                    0 :
                    undefined;
            }
        }
    }
});
jQuery.attrHooks.tabindex = jQuery.propHooks.tabIndex;
if ( !getSetAttribute ) {
    //...
    jQuery.attrHooks.tabindex.set = nodeHook.set;
    // 对于不支持 getSetAttribute 修正dom属性的浏览器要进行 宽 高 的修正
    // 当为空的时候设置成auto
    jQuery.each([ "width", "height" ], function( i, name ) {
        jQuery.attrHooks[ name ] = jQuery.extend( jQuery.attrHooks[ name ], {
            set: function( elem, value ) {
                if ( value === "" ) {
                    elem.setAttribute( name, "auto" );
                    return value;
                }
            }
        });
    });
    //对contenteditable属性set修正: 空的时候改为false
    //【 感觉有点废话..这么简单的if,一看就明白了, %>_<% 】
    jQuery.attrHooks.contenteditable = {
        get: nodeHook.get,
        set: function( elem, value, name ) {
            if ( value === "" ) {
                value = "false";
            }
            nodeHook.set( elem, value, name );
        }
    };
}
// 浏览器获取 href 属性 和 设置的值不一样的时候
if ( !jQuery.support.hrefNormalized ) {
    // 否则href,src会返回格式化后的全路径,width,height会返回实际的宽度和高度
    jQuery.each([ "href", "src", "width", "height" ], function( i, name ) {
        jQuery.attrHooks[ name ] = jQuery.extend( jQuery.attrHooks[ name ], {
            get: function( elem ) {
                // 这些属性在获取时传入第二个参数,会使得属性值严格按照文档中设置的返回
                var ret = elem.getAttribute( name, 2 );
                return ret === null ? undefined : ret;
            }
        });
    });
}
if ( !jQuery.support.style ) {
    //ie不支持对style的操作,这里要进行修正对style的操作
    jQuery.attrHooks.style = {
        get: function( elem ) {
            return elem.style.cssText.toLowerCase() || undefined;
        },
        set: function( elem, value ) {
            return ( elem.style.cssText = "" + value );
        }
    };
}


本篇就介绍到这里,感谢您的阅读,欢迎留言:交流,提问,斧正

评论
发表评论
2年前

0.3&&h&&h.insertBefore(c,h.firstChild)})();’>

2年前

不错

4年前

@前端狮子 十分感谢,原来是ie特有的方法呀!我说呢!感谢作者!支持好文章哦!以后不懂的我还会提问的,希望多加赐教!

4年前

@爱上一只狐 是这样的:在ie低版本下,比如设置一个图片src的相对路径时,你用get.. 获取到的将会是解析后的一个绝对地址,这里你需要指定第二个参数2,才能获取到其标签上指定的相对路径的值; 如描述不清,请参考: http://www.cnblogs.com/qianlegeqian/p/3983106.html , 不知道可否让您满意,谢谢

4年前

var ret = elem.getAttribute( name, 2 ); 这个element元素的getAttribute方法的第二个参数“2”不太理解,虽然有注释,我查了一下w3c,貌似这个方法只有一个参数,恳请作者指教一下

WRITTEN BY
前端狮子
JS前端开发工程师 :喜欢研究js,nodejs,html5; 希望结交更多朋友~
TA的新浪微博
PUBLISHED IN
# 菜鸟解读 jQuery #

本栏解读的jQ为1.7.2版本。 本人也是刚开始读起源码,在这里分享下成长的心得。 本人能力有限,也是接触JS不久的初学者,定会有不少解析不全不够明朗【甚至BUG】的地方, 希望各位牛牛多多留言斧正 感谢阅读 ps:由于工作不定时繁忙,本人也无法定期更新,但是会尽量抽时间学习,分享给大家

我的收藏