jQuery中的attr()和prop()的区别

先看个简单的例子:

HTML代码

<div id="container">
    <p>喜欢的水果</p>
    <input type="checkbox" class="checkbox"/>苹果<br/>
    <input type="checkbox" class="checkbox"/>橘子<br/>
    <input type="checkbox" class="checkbox"/>香蕉<br/>
    <input id="all" type="checkbox" />全选<br/>

</div>
jQuery代码
<script>
    $(function(){
        var btn = true;
        $('#all').click(function(){
            if(!btn){
               $('.checkbox').attr('checked',false);
            }else{
                $('.checkbox').attr('checked',true);
            }
            btn = !btn;

        });
    });
</script>
当我们使用上面的方法时,你会发现只有第一次的时候点击全选按钮可以达到全选功能,但当我们第二次想要达到全选功能的时候,怎么点击都不起作用,怎么解决呢?很简单,看下面的代码
<script>
    $(function(){
        var btn = true;
        $('#all').click(function(){
            if(!btn){
                $('.checkbox').prop('checked',false);
            }else{
                $('.checkbox').prop('checked',true);
            }
            btn = !btn;

        });
    });
</script>
嗯、细心的人会发现,这两段代码的区别就是把attr换成了prop,对就这么简单就可以,那么为什么呢?且听我娓娓道来

先搞懂 attribute 与 property

当编写 HTML 源码时,你能在 HTML 元素里定义 attributes。然后,一旦浏览器解析你的代码,该 HTML 元素相应的 DOM 节点就会被创建。该节点是一个对象,因此它就拥有 properties。
因此,我们知道:attributes 是 HTML 元素(标签)的属性,而 properties 是 DOM 对象的属性。

例如,下面这个 HTML 元素:

<input type="text" value="Name:">

拥有两个 attributes。

一旦浏览器解析该代码,HTMLInputElement 对象就会被创建,并且该对象会拥有很多 peoperties,如:accept、accessKey、align、alt、attributes、autofocus、baseURI、checked、childElementCount、ChildNodes、children、classList、className、clientHeight 等等。

对于某个 DOM 节点对象,properties 是该对象的所有属性,而 attributes 是该对象对应元素(标签)的属性。(即写在HTML标签中的属性)

当一个 DOM 节点为某个 HTML 元素所创建时,其大多数 properties 与对应 attributes 拥有相同或相近的名字,但这并不是一对一的关系。例如,下面这个 HTML 元素:

<input id="input" type="text" value="Name:">

其对应 DOM 节点会拥有如下properties: id、type 和 value:

id  property是id  attribute的映射:获取该property即等于读取其对应的attribute值,而设置该property即为attribute赋值。id是一个纯粹的映射property,它不会修改或限制其值。

type  property是type   arrtibute的映射:获取该property即等于读取其对应的attribute值,而设置该property即为attribute赋值。但type并不是一个纯粹的映射property,因为它的值被限制在已知值(即input的合法类型,如text、password、url)。如果你有<input type="leo">那么input.getAttribute('type')会返回leo,而input.type会返回text

相比之下,value  property并不会映射value  attribute。取而代之的是input的当前值。当用户手动更改输入框的值,value  property会反映该改变。所以,当用户在input输入donna,input.value会返回donna,而input.getAttribute('value')返回“Name”

value  property反映了input的当前文本内容,而value  attribute则是在HTML源码value属性所指定的初始文本

再看看 attr() 与 prop() 的区别

上述能让我们理清了 attribute 与 property 之间的区别,下面根据jQuery文档对 attr() 与 prop() 方法进行比较:

自jQuery1.6版本起,attr()方法对于未设置的attribute(即标签中没有写该attribute)都会返回undefined。对于检索DOM的properties,如表单圆度的checked、selected或disabled状态应使用.prop()方法

Attributes 与 Properties的区别

在jQuery1.6前,.attr()方法在检索一些attributes时,有时会把property考虑进去,这会导致不一致的行为。在1.6之后.prop()方法提供了一种明确检索property值的方式,而.attr只会检索attributes

根据W3C forms(表单)规范,checked是一个值为Boolean的attribute,这意味着当该attribute存在(无论值是什么),其对应的property都是true。

然而,对于checked attribute最重要的概念是记住它并不是对应checked  property。该attribute实际上对应defaultChecked  property,并仅在初次设置checkbox值时使用。checkedattribute的值并不会随着checkbox的状态而做出相应的改变,而checked property 会,因此,为了兼容不同浏览器,当判断一个checked是否被选择时应该使用property

if (elem.checked)
if ($(elem).prop("checked"))
if ($(elem).is(":checked"))

这同样适用于其它动态 attributes,如 selected 和 value。

所以现在就可以解决上面我们的问题,为什么当我们使用attr()时,只有第一次点击全选起作用,而后面无论怎么点击都不会起作用,原因就是因为第一次使用时,相当于我们为input添加了一个属性checked,而它的默认值为true,所以我们点击的时候达到了全选的效果,而当我们后面点击的时候checkedattribute的值并不会随着checkbox的状态而做出相应的改变,所以当我们改变attr(),即改变attribute时,并不会起作用。而checked property 会,因此,使用prop()是不会有bug的。

其他说明:
在 IE9 之前的版本,如果使用.prop()为 DOM 元素的 property 设置的值不是一个简单的原始值(number、string 或 boolean),且该 property 在 DOM 元素从 document 移除前未被移除(使用 .removeProp()),则会导致内存泄漏。为 DOM 对象设置值的安全做法(避免内存泄漏)是使用.data()

既然提高了.data(),那么咱就稍微的聊聊它

.data()

data()方法向被选元素附加数据,或者从被选元素获取数据

从元素返回数据:

  • 语法:$(elem).data(name)。可选,规定要取回的数据的名称,如果没有规定名称,则该方法将以对象的形式从元素中返回所有存储的数据

向元素附加数据(向被选元素附加数据)

  • 语法:$(elem).data(name,value)。两个都不可少,name规定要设置的数据的名称,value规定要设置的数据的值

那么data有什么作用呢?

  在我们平时js编码过程中,我们经常会向DOM元素中添加各种自定义属性,这样有一个弊端。

  1  假设我们在DOM元素中添加了一个属性,这个属性指向了某个js对象。 dom1.ele = jsObj

  2  当这个js对象发挥完作用后,我们已经用不到他了。这时候按理说应该把这个js变量清空,释放内存。大家都知道,如果一个js对象不存在任何外在引用的话,解释器会自动将其在内存中删除,这也是javascript相对于c++等手动管理内存的程序的优点。

  3  但是这时候问题来了,因为DOM元素引用了这个js对象,尽管这个js对象已经没有存在的意义了,但是解释器是不会把他删除的。如果想要把其删除,我们可能需要将DOM元素的这个属性设置为null。

  4  我们编写了这么多的代码,哪里能把 每个js对象是不是被DOM元素引用了都记住啊?

  5  而且,假如DOM元素与js对象之间相互循环引用,根本就无法删除! 这就是内存泄漏

  6  所以,为了避免这种情况的发生,我们要尽量避免 引用数据(这里的引用数据可以说是javascript对象) 直接依附在DOM对象上。

  7  data就是用来搞定以上问题的方法。

data是如何解决上面的问题的?

  1  首先我们创建一个数据缓存池,这个缓存池专门用来存储  向 DOM对象或者jQuery对象附加的额外数据。

  2  当我们要向DOM对象或者jQuery对象附加额外数据的时候,我们附加的数据其实是保存于这个缓存池中

  3  DOM对象或者jQuery对象生成一个额外属性,这个属性保存了 附加数据在缓存池中的‘门牌号’(位置或者索引)

  4  当我们访问DOM对象或者jQuery对象的附加数据时,实际上是先取得其附加数据的门牌号,然后找到缓存池中对应门牌号的数据,进行操作。

总结: data实际上就是对js对象或者DOM对象的额外属性做了一个集中的管理。对于那些不会产生内存泄漏的额外数据,我们也可以直接向js对象或者DOM对象附加。


  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值