jQuery提供了一些快捷函数来对dom对象的属性进行存取操作. 这一部分还是比较简单的.

根据API这章主要是分解5个方法

  • .attr()   获取匹配的元素集合中的第一个元素的属性的值  或 设置每一个匹配元素的一个或多个属性。
  • .prop() 获取匹配的元素集中第一个元素的属性(property)值或设置每一个匹配元素的一个或多个属性。
  • .removeAttr() 为匹配的元素集合中的每个元素中移除一个属性(attribute)。
  • .removeProp() 为集合中匹配的元素删除一个属性(property)。
  • .val() 获取匹配的元素集合中第一个元素的当前值或设置匹配的元素集合中每个元素的值

jQuery的主要工作还是为了解决浏览器的兼容性. 这部分的方法一般都有2个特点.

  • set方法和get方法一体化. 根据参数数量来判断是set还是get.
  • value可以传入一个闭包. 这个闭包的返回值才是真正的value.

先看一组HTML结构

<input id="Aaron" type="checkbox" checked="checked" />

用attr,与prop取值出input元素上的checked

分别会取得什么值?

$('input').attr('checked')  //checked 

$('input').prop('checked')  // true

看到这里应该知道这两个方法的区别了。其实从方法名也可以大致猜出来,.attr()、.prop()分别取的是节点的attribute值、property值。


attribute和property的区别

attribute:特性

  • 直接写在标签上的属性,可以通过setAttribute、getAttribute进行设置、读取

property:属性

  • 通过“.”号来进行设置、读取的属性,就跟Javascript里普通对象属性的读取差不多

观察一张图很直观的理解:

attributes是一个类数组的容器,说得准确点就是NameNodeMap,总之就是一个类似数组但又和数组不太一样的容器。attributes的每个数字索引以名值对(name=”value”)的形式存放了一个attribute节点。

attributes是会随着添加或删除attribute节点动态更新的。

特性的操作:

  • getAttribute
  • setAttribute
  • removeAttribute

property就是一个属性,如果把DOM元素看成是一个普通的Object对象,那么property就是一个以名值对(name=”value”)的形式存放在Object中的属性。要添加和删除property也简单多了,和普通的对象没啥分别。

之所以attribute和property容易混倄在一起的原因是,很多attribute节点还有一个相对应的property属性

DOM元素一些默认常见的attribute节点都有与之对应的property属性,比较特殊的是一些值为Boolean类型的property,如一些表单元素。

总的来说:基本可以总结为attribute节点都是在HTML代码中可见的,而property只是一个普通的名值对属性


  • jQuery.prototype.attr
  • jQuery.prototype.prop
  • jQuery.prototype.removeAttr
  • jQuery.prototype.removeProp
  • jQuery.prototype.val

jQuery把又长又难记的函数用外观模式包装成attr,prop,内部setAttribute,getAttribute是低级API,实现核心功能, 从而隐藏了用户程序对jQuery各个模块调用的复杂性

看看源码的实现

attr: function( ele, value ) {
return jQuery.access( this, jQuery.attr, name, value, arguments.length > 1 );
},
prop: function( name, value ) {
return jQuery.access( this, jQuery.prop, name, value, arguments.length > 1 );
},

暴露给api的原型方法非常简单,只有一句话.把参数交给jQuery.access函数去处理. jQuery.access主要作用是修正参数.

access函数里的第二个参数jQuery.attr. 这个参数的作用是告诉access方法, 修正完参数后再去调用 jQuery.attr方法.

access方法是可以被抽象出复用的一组对参数的修正方法,通过分解成单一的数据后,然后调用传递的回调处理钩子 比如 attr,css, prop.等等

jQuery.access源码	// Multifunctional method to get and set values of a collection
// The value/s can optionally be executed if it's a function
access: function( elems, fn, key, value, chainable, emptyGet, raw ) {
var i = 0,
length = elems.length,
bulk = key == null; // Sets many values
if ( jQuery.type( key ) === "object" ) { //传递是对象
chainable = true;
for ( i in key ) { //递归调用
jQuery.access( elems, fn, i, key[i], true, emptyGet, raw );
} // Sets one value
} else if ( value !== undefined ) {
chainable = true; if ( !jQuery.isFunction( value ) ) {
raw = true;
} if ( bulk ) {
// Bulk operations run against the entire set
if ( raw ) {
fn.call( elems, value );
fn = null; // ...except when executing function values
} else {
bulk = fn;
fn = function( elem, key, value ) {
return bulk.call( jQuery( elem ), value );
};
}
} if ( fn ) {
for ( ; i < length; i++ ) {
fn( elems[i], key, raw ? value : value.call( elems[i], i, fn( elems[i], key ) ) );
}
}
} return chainable ?
elems : // Gets
bulk ?
fn.call( elems ) :
length ? fn( elems[0], key ) : emptyGet;
},

access源码部分比较简单, 就是对象传参分解成单一的参数从而set,get处理


关于jQuery Hooks

你知道一些核心jQuery函数都有自己的“插件API”称为“钩子”?

详见:http://blog.rodneyrehm.de/archives/11-jQuery-Hooks.html

大概意思如下:

jQuery提供一个API来调用用户自定义的函数,用于扩展,以便获取和设置特定属性值

主要是:.attr(), .prop(), .val() and .css()四种类型的处理

钩子都有相似的结构

var someHook = {
get: function(elem) {
// obtain and return a value
return "something";
},
set: function(elem, value) {
// do something with value
}
}

如何使用?

用jQuery官方提供的为列 http://www.css88.com/jqapi-1.9/jQuery.cssHooks/

在做css3属性浏览器兼容的时候,都需要特定的前缀

Webkit的浏览器:-webkit-border-radius

Firefox:-moz-border-radius

此时我看可以采用一个CSS hook 可以标准化这些供应商前缀的属性,让.css() 接受一个单一的,标准的属性的名称(border-radius,或用DOM属性的语法,borderRadius

判断的代码省略,直接看实现

给某一元素设置borderRadius,为10px

$("#element").css("borderRadius", "10px");

为了做浏览器兼容,我们不得不

if(webkit){
........................
}else if(firefox){
............................
}else if(...)更多

这是一种最没技术含量的写法了,如果我们换成一种hook的话

$.cssHooks.borderRadius = {
get: function( elem, computed, extra ) {
return $.css( elem, borderRadius );
},
set: function( elem, value) {
elem.style[ borderRadius ] = value;
}
};

borderRadius = styleSupport( "borderRadius" ); //获取到相对应的浏览器标准

这里可能还不直观的体现,我们深入到attr源码中看看


jQuery.attr 静态方法

jQuery实例的方法都是调用最终的静态方法:jQuery.attr

access函数最后把参数又传递给了jQuery.attr, 在jQuery.attr里才真正进行setAttribute/getAttribute操作.

查看源码关于attrHooks一个type

意思就是在使用attr(‘type’,??)设置的时候就会调用这个hooks,用于处理IE6-9 input属性不可写入的问题

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;
}
}
}
},

省略部分代码attr源码

  • 通过hooks = jQuery.attrHooks[ name ]方法,去适配对应的name,是否在合集中
  • 如果是hooks然后又是get方法就调用 hooks && "set" in hooks && (ret = hooks.set( elem, value, name )
  • 如果有ret返回值就return(hooks.set可能还不是最终匹配)
  • 否则继续往下走

其实这样的思路,在sizzle选择器也大量的运用了

钩子就是适配器原理,用来处理一些特殊的属性,样式或事件。而这些属性,样式或事件,我们可以通过浏览器的特征嗅探,把相应的解决方法添加到适配器中。有了这些适配器,jQuery就可以省去许多if else 判定


那么,利用钩子处理兼容与扩展的好处:

  • 适配器这种模式对于扩展新功能非常有利
  • 如果采用钩子处理的话,我们就省去了一大堆if else的分支判断
  • 由于JS用对象做为表进行查找是比if条句与switch语句快很多

本章的重点在于如何灵活运用运用钩子的原理,在实际项目中更好的处理兼容与扩展

jQuery 2.0.3 源码分析 钩子机制 - 属性操作的更多相关文章

  1. jQuery 2.0.3 源码分析Sizzle引擎解析原理

    jQuery 2.0.3 源码分析Sizzle引擎 - 解析原理 声明:本文为原创文章,如需转载,请注明来源并保留原文链接Aaron,谢谢! 先来回答博友的提问: 如何解析 div > p + ...

  2. jQuery 2.0.3 源码分析 Deferred(最细的实现剖析,带图)

    Deferred的概念请看第一篇 http://www.cnblogs.com/aaronjs/p/3348569.html ******************构建Deferred对象时候的流程图* ...

  3. jQuery 2.0.3 源码分析core - 选择器

         声明:本文为原创文章,如需转载,请注明来源并保留原文链接Aaron,谢谢!      打开jQuery源码,一眼看去到处都充斥着正则表达式,jQuery框架的基础就是查询了,查询文档元素对象 ...

  4. jQuery 2.0.3 源码分析 Deferred概念

    JavaScript编程几乎总是伴随着异步操作,传统的异步操作会在操作完成之后,使用回调函数传回结果,而回调函数中则包含了后续的工作.这也是造成异步编程困难的主要原因:我们一直习惯于“线性”地编写代码 ...

  5. jQuery 2.0.3 源码分析 事件绑定 - bind/live/delegate/on

    事件(Event)是JavaScript应用跳动的心脏,通过使用JavaScript ,你可以监听特定事件的发生,并规定让某些事件发生以对这些事件做出响应 事件的基础就不重复讲解了,本来是定位源码分析 ...

  6. jQuery 2.0.3 源码分析 事件体系结构

    那么jQuery事件处理机制能帮我们处理那些问题? 毋容置疑首先要解决浏览器事件兼容问题 可以在一个事件类型上添加多个事件处理函数,可以一次添加多个事件类型的事件处理函数 提供了常用事件的便捷方法 支 ...

  7. jQuery 2.0.3 源码分析 Deferrred概念

    转载http://www.cnblogs.com/aaronjs/p/3348569.html JavaScript编程几乎总是伴随着异步操作,传统的异步操作会在操作完成之后,使用回调函数传回结果,而 ...

  8. jQuery 2.0.3 源码分析 样式操作

    根据API分类 CSS addClass() jQuery.cssHooks .hasClass() .removeClass() .toggleClass() .addClass() 对元素的样式操 ...

  9. jQuery 2.0.3 源码分析core - 整体架构

    拜读一个开源框架,最想学到的就是设计的思想和实现的技巧. 废话不多说,jquery这么多年了分析都写烂了,老早以前就拜读过, 不过这几年都是做移动端,一直御用zepto, 最近抽出点时间把jquery ...

随机推荐

  1. 再记录一下如何配置oracle instantclient

    这问题遇到很多次,每次重装系统就遇到一次,却总是搞半天才搞定. 今天再次花费几个小时解决,终于有一个清晰的认识必须记录一下. 一.下载解压,不建任何目录,直接复制tnsname.ora过来.(当然也可 ...

  2. BZOJ‘s Usaco 奶牛题集锦

    1230 线段树 1231 状压DP 1232 最小生成树 1527 贪心 1600 打表找规律 1601 最小生成树 1602 prime 1606 DP 1607 筛法 1609 DP 1610 ...

  3. ajax和jquery

    ajax的定义: AJAX即“Asynchronous Javascript And XML”(异步JavaScript和XML),是指一种创建交互式网页应用的网页开发技术. AJAX = 异步 Ja ...

  4. 解决IE6/IE7/IE8不支持before,after问题

    对从事web开发的朋友来讲,低版本的IE永远是一个痛点,不支持最新技术(如css3,html5). 在现在web开发中使用图标字体已经很广泛,如Font Awesome,Bootstrap等,字体图片 ...

  5. 如何用js得到当前页面的url信息方法(JS获取当前网址信息)

    设置或获取对象指定的文件名或路径. alert(window.location.pathname) 设置或获取整个 URL 为字符串. alert(window.location.href); 设置或 ...

  6. jQuery基础的工厂函数以及定时器的经典案例

    1. jQuery的基本信息:  1.1 定义: jQuery是JavaScript的程序库之一,它是JavaScript对象和实用函数的封装, 1.2 作用: 许多使用JavaScript能实现的交 ...

  7. phpcms v9常用方法

    1.联动菜单根据地区id显示地区名称的方法: 显示效果: 四川 >> 攀枝花 >> 仁和区 [字段名字为 area] {get_linkage($info['area'],1, ...

  8. Twitter面试题蓄水池蓄水量算法(原创 JS版,以后可能会补上C#的)

    之前在群里有人讨论Twitter的面试题,蓄水池蓄水量计算,于是自己写了个JS版的(PS:主要后台代码还要编译,想想还是JS快,于是就使用了JS了.不过算法主要还是思路嘛,而且JS应该都没问题吧^_^ ...

  9. USACO翻译:USACO 2012 JAN三题(1)

    USACO 2012 JAN(题目一) 一.题目概览 中文题目名称 礼物 配送路线 游戏组合技 英文题目名称 gifts delivery combos 可执行文件名 gifts delivery c ...

  10. 编写一个基本的连接池来实现连接的复用&一些工程细节上的优化

    package it.cast.jdbc; import java.sql.Connection; import java.sql.DriverManager; import java.sql.SQL ...