zoukankan      html  css  js  c++  java
  • 对jquery的 attr()和prop()理解

    jquery1.6版本后引入了prop()方法,很多时候总是混淆attr()与prop()这俩,下面分析一下这俩的区别

    在此之前,先来了解一下html 的attribute和property,因为jquery的attr()和prop()正是来源于这俩东西。先看一段html代码:

    <span  id="testId" class="testClass" selfAttribute="selfValue"></span>

    根据 DOM (HTML) 规范,SPAN 元素在页面中生成一个相对应的对象,对象有一个标识为id的attribute,对于attribute,我们称为HTML标签属性,对于property,为DOM对象属性,注意下面这句话:

    HTML 标签的属性会将其值暴露给对应的 DOM 对象的属性,如 HTML 元素的 id 属性与其对应的 DOM 对象的 id 属性会保持一种同步关系

    所以该元素的dom对象中也会生成key为id的 property,所以可以通过key直接获得值,看下面的例子

    var testId =  document.getElementById("testId");
    console.log(testId.id);//testId
    console.log(testId.getAttribute("id"));//testId

    这样一来是不是以后获取属性值都直接用.访问就可以了,下面继续看:

     var testId =  document.getElementById("testId");
     console.log(testId.class);//undefinde
     console.log(testId.getAttribute("class"));//testClass

    当我们直接访问class时,并没有得到我们期望的testClass,原因是在 HTML 标签中使用 class 属性指定元素使用的 CSS 类,但在 DOM 对象中由于 class 是 ECMAScript 的保留字,所以改用 className 属性,所以想直接获取class值,修改一下即可:

    console.log(testId.className);//testClass

    上面的例子可以知道 ,对于部分 "property" 与 "attribute" 在名称及值类型上是统一的,对于我们经常用到的自定义属性,可以继续做个测试:

     var testId =  document.getElementById("testId");
     console.log(testId.selfAttribute);//undefined
     console.log(testId.getAttribute("selfAttribute"));//selfValue

    testId.selfAttribute为undefined说明property与attribute并不共享自定义属性,引用别人的一张图来表示一下:

        

    对于build-in区域的属性,property和attribute是共享的,比如id,但是IE6、7没有作区分,依然共享自定义属性数据,因为IE 混淆了 DOM 对象属性(property)及 HTML 标签属性(attribute),造成了对 setAttribute、getAttribute 的不正确实现,参考http://www.w3help.org/zh-cn/causes/SD9006

    对于自定义的属性两者互不干涉,即使name是相同的,看下面例子:

     var testId =  document.getElementById("testId");
           testId.setAttribute("stk1","stv1");
           console.log(testId.stk1);//undefined
           console.log(testId.getAttribute("stk1"));//selfValue
           testId.stk1 = "stv2";
           console.log(testId.stk1);//stv2
           console.log(testId.getAttribute("stk1"));//stv1

    此外,对于值是true/false的property,类似于input的checked attribute等,attribute取得值是HTML文档字面量值,property是取得计算结果,property改变并不影响attribute字面量,但attribute改变会影响property计算

    <input type="checkbox" id="checkboxId"/>
    var checkbox1 =  document.getElementById("checkboxId");
           
             alert(checkbox1.checked);//false
             alert(checkbox1.getAttribute("checked"));//null
    
            /* checkbox1.setAttribute("checked","checked");
             alert(checkbox1.checked);//true, setAttribute影响property*/
    
             checkbox1.checked = true;
             alert(checkbox1.getAttribute("checked"));//null property不影响setAttribute影响property

    对于一些和路径相关的属性,两者取得值也不尽相同,但是同样attribute取得是字面量,property取得是计算后的完整路径

    <a id="testA" href="#">Click</a>
     var testA =  document.getElementById("testA");
     console.log(testA.href);//file:///C:/Users/%E6%B0%B8%E4%BF%A1/Desktop/static/main.html# 
     console.log(testA.getAttribute("href"));//#

    看完上面的文章,看一下主题,attr() 和 prop()

    首先贴源码:

    attr:

    attr: function( elem, name, value, pass ) {
        var ret, hooks, notxml,
            nType = elem.nodeType;
        // don't get/set attributes on text, comment and attribute nodes
        if ( !elem || nType === 3 || nType === 8 || nType === 2 ) {
            return;
        }
        if ( pass && jQuery.isFunction( jQuery.fn[ name ] ) ) {
            return jQuery( elem )[ name ]( value );
        }
        // Fallback to prop when attributes are not supported
        if ( typeof elem.getAttribute === "undefined" ) {
            return jQuery.prop( elem, name, value );
        }
        notxml = nType !== 1 || !jQuery.isXMLDoc( elem );
        // All attributes are lowercase
        // Grab necessary hook if one is defined
        if ( notxml ) {
            name = name.toLowerCase();
            hooks = jQuery.attrHooks[ name ] || ( rboolean.test( name ) ? boolHook : nodeHook );
        }
        if ( value !== undefined ) {
            if ( value === null ) {
                jQuery.removeAttr( elem, name );
                return;
            } else if ( hooks && "set" in hooks && notxml && (ret = hooks.set( elem, value, name )) !== undefined ) {
                return ret;
            } else {
                elem.setAttribute( name, value + "" );
                return value;
            }
        } else if ( hooks && "get" in hooks && notxml && (ret = hooks.get( elem, name )) !== null ) {
            return ret;
        } else {
            ret = elem.getAttribute( name );
            // Non-existent attributes return null, we normalize to undefined
            return ret === null ?
                undefined :
                ret;
        }
    }

    prop:

    prop: function( elem, name, value ) {
        var ret, hooks, notxml,
            nType = elem.nodeType;
        // don't get/set properties on text, comment and attribute nodes
        if ( !elem || nType === 3 || nType === 8 || nType === 2 ) {
            return;
        }
        notxml = nType !== 1 || !jQuery.isXMLDoc( elem );
        if ( notxml ) {
            // Fix name and attach hooks
            name = jQuery.propFix[ name ] || name;
            hooks = jQuery.propHooks[ name ];
        }
        if ( value !== undefined ) {
            if ( hooks && "set" in hooks && (ret = hooks.set( elem, value, name )) !== undefined ) {
                return ret;
            } else {
                return ( elem[ name ] = value );
            }
        } else {
            if ( hooks && "get" in hooks && (ret = hooks.get( elem, name )) !== null ) {
                return ret;
            } else {
                return elem[ name ];
            }
        }
    }

    attr方法里面,最关键的两行代码,elem.setAttribute( name, value + “” )和ret = elem.getAttribute( name ),很明显的看出来,使用的DOM的API setAttribute和getAttribute方法操作的属性元素节点
    而prop方法里面,最关键的两行代码,return ( elem[ name ] = value )和return elem[ name ],你可以理解成这样document.getElementById(el)[name] = value,这是转化成JS对象的一个属性。

    再来看例子:

    <input type="checkbox" id="test" abc="111" />
    $(function(){
        el = $("#test");
        console.log(el.attr("style"));  //undefined
        console.log(el.prop("style"));  //CSSStyleDeclaration对象
        console.log(document.getElementById("test").style); //CSSStyleDeclaration对象
    });
    1. el.attr(“style”)输出undefined,因为attr是获取的这个对象属性节点的值,很显然此时没有这个属性节点,自然输出undefined
    2. el.prop(“style”)输出CSSStyleDeclaration对象,对于一个DOM对象,是具有原生的style对象属性的,所以输出了style对象
    3. 至于document.getElementById(“test”).style和上面那条一样
    el.attr("abc","111")
    console.log(el.attr("abc")); //111
    console.log(el.prop("abc")); //undefined

    首先用attr方法给这个对象添加abc节点属性,值为111,可以看到html的结构也变了

    1. el.attr(“abc”)输出结果为111,再正常不过了
    2. el.prop(“abc”)输出undefined,因为abc是在这个的属性节点中,所以通过prop是取不到的

    我们再接着来:

    el.prop("abc", "222");
    console.log(el.attr("abc")); //111
    console.log(el.prop("abc")); //222

    我们再用prop方法给这个对象设置了abc属性,值为222,可以看到html的结构是没有变化的。输出的结果就不解释了。

    提一下,在遇到要获取或设置checked,selected,readonly和disabled等属性时,用prop方法显然更好,比如像下面这样:

    <input type="checkbox" id="test" checked="checked" />
    console.log(el.attr("checked")); //checked
    console.log(el.prop("checked")); //true
    console.log(el.attr("disabled")); //undefined
    console.log(el.prop("disabled"));  //false

    关于checked 属性需要记住的最重要的一点是:它和checked property并不是一致的。实际上这个attribute和defaultChecked property一致,而且只应该用来设置checkbox的初始值。checked attribute并不随着checkedbox的状态而改变,但是checked property却跟着变。因此浏览器兼容的判断checkebox是否被选中应该使用property

  • 相关阅读:
    BEGINNING SHAREPOINT&#174; 2013 DEVELOPMENT 第13章节--使用业务连接服务创建业务线解决方式 创建启用BCS的业务解决方式
    POI 导入excel数据自己主动封装成model对象--代码分析
    四旋翼飞行器Quadrotor飞控之 PID调节(參考APM程序)
    Detours改动段属性漏洞
    C++中父类的虚函数必需要实现吗?
    深入理解JavaScript系列(12):变量对象(Variable Object)
    CSS 类、伪类和伪元素差别具体解释
    Qt Quick 之 PathView 具体解释
    读《一年一度屈原祭,端午时节话公知》有感
    Volley简单学习使用五—— 源代码分析三
  • 原文地址:https://www.cnblogs.com/teamobaby/p/3866238.html
Copyright © 2011-2022 走看看