jQuery提供了一些快捷函数来对dom对象的属性进行存取操作. 这一部分还是比较简单的.
根据API这章主要是分解5个方法
jQuery的主要工作还是为了解决浏览器的兼容性. 这部分的方法一般都有2个特点.
先看一组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:特性
property:属性
观察一张图很直观的理解:
attributes是一个类数组的容器,说得准确点就是NameNodeMap,总之就是一个类似数组但又和数组不太一样的容器。attributes的每个数字索引以名值对(name=”value”)的形式存放了一个attribute节点。
attributes是会随着添加或删除attribute节点动态更新的。
特性的操作:
property就是一个属性,如果把DOM元素看成是一个普通的Object对象,那么property就是一个以名值对(name=”value”)的形式存放在Object中的属性。要添加和删除property也简单多了,和普通的对象没啥分别。
之所以attribute和property容易混倄在一起的原因是,很多attribute节点还有一个相对应的property属性
DOM元素一些默认常见的attribute节点都有与之对应的property属性,比较特殊的是一些值为Boolean类型的property,如一些表单元素。
总的来说:基本可以总结为attribute节点都是在HTML代码中可见的,而property只是一个普通的名值对属性
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源码
access源码部分比较简单, 就是对象传参分解成单一的参数从而set,get处理
你知道一些核心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源码
其实这样的思路,在sizzle选择器也大量的运用了
钩子就是适配器原理,用来处理一些特殊的属性,样式或事件。而这些属性,样式或事件,我们可以通过浏览器的特征嗅探,把相应的解决方法添加到适配器中。有了这些适配器,jQuery就可以省去许多if else 判定
那么,利用钩子处理兼容与扩展的好处:
本章的重点在于如何灵活运用运用钩子的原理,在实际项目中更好的处理兼容与扩展