先看个简单的例子:
HTML代码
jQuery代码
当我们使用上面的方法时,你会发现只有第一次的时候点击全选按钮可以达到全选功能,但当我们第二次想要达到全选功能的时候,怎么点击都不起作用,怎么解决呢?很简单,看下面的代码
嗯、细心的人会发现,这两段代码的区别就是把attr换成了prop,对就这么简单就可以,那么为什么呢?且听我娓娓道来
先搞懂 attribute 与 property
当编写 HTML 源码时,你能在 HTML 元素里定义 attributes。然后,一旦浏览器解析你的代码,该 HTML 元素相应的 DOM 节点就会被创建。该节点是一个对象,因此它就拥有 properties。
因此,我们知道:attributes 是 HTML 元素(标签)的属性,而 properties 是 DOM 对象的属性。
例如,下面这个 HTML 元素:
拥有两个 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 元素:
其对应 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
这同样适用于其它动态 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是如何解决上面的问题的?
数据缓存池,这个缓存池专门用来存储 向 DOM对象或者jQuery对象附加的额外数据。
2 当我们要向DOM对象或者jQuery对象附加额外数据的时候,我们附加的数据其实是保存于这个缓存池中
额外属性,这个属性保存了 附加数据在缓存池中的‘门牌号’(位置或者索引)
4 当我们访问DOM对象或者jQuery对象的附加数据时,实际上是先取得其附加数据的门牌号,然后找到缓存池中对应门牌号的数据,进行操作。
总结: data实际上就是对js对象或者DOM对象的额外属性做了一个集中的管理。对于那些不会产生内存泄漏的额外数据,我们也可以直接向js对象或者DOM对象附加。