從零開始學習jQuery (一) 開天闢地入門篇
從零開始學習jQuery (二) 萬能的選擇器
從零開始學習jQuery (三) 管理jQuery包裝集
從零開始學習jQuery (四) 使用jQuery操作元素的屬性與樣式
從零開始學習jQuery (五) 事件與事件對象
從零開始學習jQuery (六) jQuery中的Ajax
#從零開始學習jQuery (七) jQuery動畫-讓頁面動起來!
從零開始學習jQuery (八) 插播:jQuery實作方案
從零開始學習jQuery (九) jQuery工具函數
從零開始學習jQuery (十) jQueryUI常用功能實戰
從零開始學習jQuery (十一) 實戰表單驗證與自動完成提示外掛
本系列文章將帶您進入jQuery的精彩世界, 其中有很多作者俱體的使用經驗和解決方案, 即使你會使用jQuery也能在閱讀中發現些許秘籍.
我們經常要使用腳本處理各種業務邏輯, 最常見的就是陣列和物件的操作. jQuery工具函數為我們操作物件和陣列提供了便利條件.
大部分人僅使用jQuery的選擇器選擇物件, 或實現頁面動畫效果. 在處理業務邏輯時常常自己編寫很多算法. 本文提醒各位jQuery也能提高我們操作對象和數組的效率. 並且可以將一些常用算法擴充到jQuery工具函數中, 實作腳本函數的複用.
工具函數是指在jQuery物件(即變數"$")上定義的函數. 這些函數都是工具類別函數.例如C#中最常用的trim()函數:
$.trim(" text ");
在原始javascript中並沒有提供同時去除前後空格的trim函數. 所以這一類常用的工具函數統稱為"Utilities" 函數.對應jQuery官方文件:
http://docs.jquery.com/Utilities
"$"其實是"window"物件的屬性,所以下面幾句話是等價的:
$.trim(" text "); window.$.trim(" text "); window.jQuery(" text "); jQuery.trim(" text ");
工具函數主要分為下面幾類:
瀏覽器及特性偵測
#陣列與物件操作
##測試操作
字串運算
Url動作
區別於前幾章的講解方式, 本文不在列舉函數列表. 大家在應用中, 例如遇到想操作一個字符串, 可以首先從在
"API文檔/Utilities/字串操作"中查找是否已經提供了快捷的工具函數. 如果沒有再考慮自己開發.
五.瀏覽器及特性檢測
jQuery的優秀就在於其跨瀏覽器的特性, 通常我們不用再針對不同瀏覽器書寫不同的程式碼. 但是如果是jQuery開發人員或外掛開發人員就要自行處理瀏覽器差異, 以便為使用者提供跨瀏覽器的特性.
jQuery.support | |
##jQuery .browser | 已廢除 |
#jQuery.browser.version | ##已廢除 |
jQuery.boxModel | 已廢除 |
在1.3版本中已经废除了三个属性, 这里不再讲解. 让我们将注意力放在 jQuery.support 函数上.
返回值: Object
说明:
jQuery 1.3 新增。一组用于展示不同浏览器各自特性和bug的属性集合。
jQuery提供了一系列属性,你也可以自由增加你自己的属性。其中许多属性是很低级的,所以很难说他们能否在日新月异的发展中一直保持有效,但这这些主要用于插件和内核开发者。
所有这些支持的属性值都通过特性检测来实现,而不是用任何浏览器检测。以下有一些非常棒的资源用于解释这些特性检测是如何工作的:
http://peter.michaux.ca/articles/feature-detection-state-of-the-art-browser-scripting
http://yura.thinkweb2.com/cft/
http://www.jibbering.com/faq/faq_notes/not_browser_detect.html
jQuery.support主要包括以下测试:
boxModel: 如果这个页面和浏览器是以W3C CSS盒式模型来渲染的,则等于true。通常在IE 6和IE 7的怪癖模式中这个值是false。在document准备就绪前,这个值是null。
cssFloat: 如果用cssFloat来访问CSS的float的值,则返回true。目前在IE中会返回false,他用styleFloat代替。
hrefNormalized: 如果浏览器从getAttribute("href")返回的是原封不动的结果,则返回true。在IE中会返回false,因为他的URLs已经常规化了。
htmlSerialize: 如果浏览器通过innerHTML插入链接元素的时候会序列化这些链接,则返回true,目前IE中返回false。
leadingWhitespace: 如果在使用innerHTML的时候浏览器会保持前导空白字符,则返回true,目前在IE 6-8中返回false。
noCloneEvent: 如果浏览器在克隆元素的时候不会连同事件处理函数一起复制,则返回true,目前在IE中返回false。
objectAll: 如果在某个元素对象上执行getElementsByTagName("*")会返回所有子孙元素,则为true,目前在IE 7中为false。
opacity: 如果浏览器能适当解释透明度样式属性,则返回true,目前在IE中返回false,因为他用alpha滤镜代替。
scriptEval: 使用 appendChild/createTextNode 方法插入脚本代码时,浏览器是否执行脚本,目前在IE中返回false,IE使用 .text 方法插入脚本代码以执行。
style: 如果getAttribute("style")返回元素的行内样式,则为true。目前IE中为false,因为他用cssText代替。
tbody: 如果浏览器允许table元素不包含tbody元素,则返回true。目前在IE中会返回false,他会自动插入缺失的tbody。
讲解:
针对上面众多的浏览器特性属性, 本文只讲解两个特性.
下图是W3C标准中的盒式模型图:
假设如下元素:
<style type="text/css">.boxModel { width:200px; height:50px; padding:10px; border:solid 5px #FF0000; background-color:#acacac; }</style><p id="pBox" class="boxModel">
显示效果如图:
在CSS中设定元素宽度为200px, 下面以此元素为例讲解盒式模式.
元素的宽度和高度为盒式模型图中的Context部分, 不包括padding, border和margin部分.
目前除了IE所有的浏览器都仅支持W3C盒式模型. 在W3C盒式模型中, 示例中包含红框在内的区域内容宽度为200+2*10+2*5=230px, 高度为50+2*10+2*5=80px.
设置的宽度包括padding,border. 实际内容宽度content Width = width - padding – border
在IE5.5及更早的版本中, 使用了此模型. 在更高的IE版本上如果由于某些原因让浏览器运行在怪异模式下则也会使用此盒式模式.所以需要在页面上声明正确的DOCTYPE. 有关DOCTYPE请参考此文:
http://www.cnblogs.com/zhangziqiu/archive/2009/01/15/doctype.html
下面是两种盒式模式的对比:
我们可以使用 jQuery.support.boxModel 属性来获取浏览器是否使用了W3C盒式模型. true表示使用W3C boxModel.
通过javascript脚本设置元素的float样式时, IE和FireFox存在不同, IE使用style.styleFloat, FireFox使用style.cssFloat:
p.style.styleFloat = ; p.stlye.cssFloat = ; //FF
jQuery.support.cssFloat 属性返回true则表示可以使用cssFloat来设置float样式. IE中返回false;
注意, 我们可以通过CSS()方法设置float样式, jQuery内部会自动帮我们判断是使用styleFloat还是cssFloat:
$("#pResult").css("float","left"); //兼容IE和FF
实现UI我们常常操作DOM对象或者jQuery包装集, 但是实现算法或者业务逻辑时往往操作的是数组和对象.
下面讲解最常用的数组和对象相关的工具函数.
jQuery.each( object, callback )
返回值:Object
说明:
通用例遍方法,可用于例遍对象和数组。
不同于例遍 jQuery 对象的 $().each() 方法,此方法可用于例遍任何对象。回调函数拥有两个参数:第一个为对象的成员或数组的索引,第二个为对应变量或内容。如果需要退出 each 循环可使回调函数返回 false,其它返回值将被忽略。
讲解:
对于jQuery包装集我们可以使用each(callback)方法迭代包装集中的每一个元素. callback是一个会函数, 接受一个参数表示当前访问对象的索引.
$("img").each(function(i){ this.src = "test" + i + ".jpg"; });
对于数组我们可以使用 jQuery.each( object, callback ) 来遍历, 这等同于使用for循环.
注意传入的第一个参数可以是数组或者对象.如果数组,则遍历数组中的每一个对象. 第一个参数表示索引,第二个参数表示值, this表示当前遍历的元素, 可以通过返回false终止迭代, 比如下面的示例遍历到第二个元素后会终止:
$.each(["a", "b", "c"], function(i, n) { alert("Item #" + i + ": " + n);//可以获取到i值 if (i >= 1) { return false; } });
$("#iterateArray").click(function(event) { var array = $.each(["a", "b", "c"], function(i, n) { alert("Item #" + i + ": " + n ); //第一个参数i表示索引, this表示当前遍历的对象 if (i >= 1) { return false; } }); });
如果传递的是对象, 则遍历对象的每一个属性, 即使函数返回false也依然会遍历完所有的属性, 第一个参数表示属性key(属性名称,是obejct类型),第二个参数表示值,,this表示当前属性的值:
$("#iterateObject").click(function(event) { $.each({ name: "ziqiu.zhang", sex: "male", status: "single" }, function(i, n) { alert("Item #" + i.toString() + ": " + n ); //第一个参数i表示属性的key(object), this表示属性值 if (i >= 1) { return false; } }); });
each将是我们最常使用的函数, 特别注意each虽然迭代每一个元素或属性, 但是在迭代函数中并不会改变当前元素的值, 也就是无法改变返回后的对象.如果需要改变数组中的每一个元素并且将结果返回, 因使用jQuery.map( array, callback )函数.
jQuery.grep( array, callback, [invert] )
返回值: Array
说明:
使用过滤函数过滤数组元素。
此函数至少传递两个参数:待过滤数组和过滤函数。过滤函数必须返回 true 以保留元素或 false 以删除元素。
讲解:
默认invert为false, 即过滤函数返回true为保留元素. 如果设置invert为true, 则过滤函数返回true为删除元素.
下面的示例演示如何过滤数组中索引小于 0 的元素:
$.grep( [0,1,2], function(n,i){ return n > 0; });
返回的结果是[1,2]
jQuery.map( array, callback )
返回值:Array
说明:
将一个数组中的元素转换到另一个数组中。
作为参数的转换函数会为每个数组元素调用,而且会给这个转换函数传递一个表示被转换的元素作为参数。转换函数可以返回转换后的值、null(删除数组中的项目)或一个包含值的数组,并扩展至原始数组中。
讲解:
1.3.2版本中此函数和each函数已经几乎相同(以前稍有不同), 现在唯一的区别就是回调函数可以改变当前元素.返回null则删除当前元素.
下面是几个例子:
var arr = [ "a", "b", "c", "d", "e" ] $("p").text(arr.join(", ")); arr = jQuery.map(arr, function(n, i){ return (n.toUpperCase() + i); }); $("p").text(arr.join(", ")); arr = jQuery.map(arr, function (a) { return a + a; }); $("span").text(arr.join(", "));
合并对象是我们常常编写的功能, 通常使用臃肿的for循环来进行.jQuery为我们提供了很多功能的合并函数:
名称 | 说明 | 举例 |
jQuery.extend( [deep], target, object1, [objectN] ) | 用一个或多个其他对象来扩展一个对象,返回被扩展的对象。 如果不指定target,则给jQuery命名空间本身进行扩展。这有助于插件作者为jQuery增加新方法。 如果第一个参数设置为true,则jQuery返回一个深层次的副本,递归地复制找到的任何对象。否则的话,副本会与原对象共享结构。 为定义的属性将不会被复制,然而从对象的原型继承的属性将会被复制。 | 合并 settings 和 options,修改并返回 settings:
var settings = { validate: false, limit: 5, name: "foo" };
<br/>var options = { validate: true, name: "bar" };
<br/>jQuery.extend(settings, options);
结果: settings == { validate: true, limit: 5, name: "bar" }
|
jQuery.makeArray( obj ) | 将类数组对象转换为数组对象。 类数组对象有 length 属性,其成员索引为 0 至 length - 1。实际中此函数在 jQuery 中将自动使用而无需特意转换。 | 将DOM对象集合转换为数组:
var arr = jQuery.makeArray(document.getElementsByTagName("p")); |
jQuery.inArray( value, array ) | 确定第一个参数在数组中的位置,从0开始计数(如果没有找到则返回 -1 )。 | 查看对应元素的位置:
var arr = [ 4, "Pete", 8, "John" ]; jQuery.inArray("John", arr); //3 jQuery.inArray(4, arr); //0 jQuery.inArray("David", arr); //-1 登入後複製 |
jQuery.merge( first, second ) | 合并两个数组 返回的结果会修改第一个数组的内容——第一个数组的元素后面跟着第二个数组的元素。要去除重复项,请使用$.unique() | 合并两个数组到第一个数组上:
$.merge( [0,1,2], [2,3,4] )
结果: [0,1,2,2,3,4] 登入後複製 |
jQuery.unique( array ) | 删除数组中重复元素。只处理删除DOM元素数组,而不能处理字符串或者数字数组。 | 删除重复 p 标签:
$.unique(document.getElementsByTagName("p"));
[<p>, <p>, ...] 登入後複製 |
讲解:
上面的函数看着有些混乱. 看看我们以后会常用的.
首先是jQuery.merge( first, second ), 将两个数组合并. 下面这个示例说明如何使用此函数:
<html xmlns="http://www.w3.org/1999/xhtml"><head> <title>jQuery Utilities - jQuery.merge</title> <script src="../scripts/jquery-1.3.2-vsdoc2.js" type="text/javascript"></script> <script type="text/javascript"> $(function() { $("#go").click(function(event) { $("#pResult").html(""); var first = [1, 3, 5]; $("#pResult").append("<span>first:[" + first.join(",") + "]</span>").append("<br/>"); var second = [2, 4, 6]; $("#pResult").append("<span>second:[" + second.join(",") + "]</span>").append("<br/>"); var result = $.merge(first, second); $("#pResult").append("<span>result:[" + result.join(",") + "]</span>").append("<br/>"); $("#pResult").append("<span>first after merged:[" + first.join(",") + "]</span><br/>"); $("#pResult").append("<span>second after merged:[" + second.join(",") + "]</span><br/>"); }); }); </script></head><body> <button id="go"> 合并数组</button> <br /> <p id="pResult"> </p></body></html>
结果如图:
另外不能因为有了jQuery就忘记我们的原始javascript. 比merge更常用的其实是join和split函数.
merge函数会改变第一个合并的数组, 如果是我设计我就不会这么做. 因为返回值已经是合并后的数组了.如此设计让函数产生歧义.
列表中的那么多函数不再一一讲解. 先用先查. 除了 jQuery.extend 这个不得不提的函数. 下面单提一个小结讲解.
在开发插件的时候最常用此函数函数来处理options.
下面是fancybox插件获取options的代码:
settings = $.extend({}, $.fn.fancybox.defaults, settings);
上面的代码target是一个空对象, 将默认设置defaults作为第一个对象, 将用户传入的设置setting合并到default上, setting上有的属性以setting为准. setting没有传入的属性则使用default的默认值. 然后将合并的结果复制给target并作为函数返回值返回.
看一个完整的示例:
var empty = {}var defaults = { validate: false, limit: 5, name: "foo" };var options = { validate: true, name: "bar" };var settings = jQuery.extend(empty, defaults, options);
结果:
settings == { validate: true, limit: 5, name: "bar" } empty == { validate: true, limit: 5, name: "bar" }
target参数要传递一个空对象是因为target的值最后将被改变.比如:
var defaults = { validate: false, limit: 5, name: "foo" }; var options = { validate: true, name: "bar" }; var settings = jQuery.extend(defaults, options);
上面的代码将defaults作为target参数, 虽然最后settings的结果一样, 但是defaults的值被改变了! 而插件中的默认值应该都是固定! 所以使用时请注意target参数的用法.
下面是我的完整示例和结果:
<html xmlns="http://www.w3.org/1999/xhtml"><head> <title>jQuery Utilities - jQuery.extend</title> <script src="../scripts/jquery-1.3.2-vsdoc2.js" type="text/javascript"></script> <script type="text/javascript"> $.toObjectString = function (obj) { var result = "{"; var counter = 0; $.each(obj, function(i, n) { if (counter > 0) { result += ","; } result += i.toString() + ":" + n.toString(); counter++; }); result += "}"; return result; } $(function() { $("#go1").click(function(event) { $("#pResult").html(""); var empty = {} var defaults = { validate: false, limit: 5, name: "foo" }; var options = { validate: true, name: "bar" }; $("#pResult").append("<span>empty:" + $.toObjectString(empty) + "</span>").append("<br/>"); $("#pResult").append("<span>defaults:" + $.toObjectString(defaults) + "</span>").append("<br/>"); $("#pResult").append("<span>options:" + $.toObjectString(options) + "</span>").append("<br/>"); var settings = jQuery.extend(empty, defaults, options); $("#pResult").append("<span>settings after extend:" + $.toObjectString(settings) + "</span>").append("<br/>"); $("#pResult").append("<span>defaults after extend:" + $.toObjectString(defaults) + "</span>").append("<br/>"); $("#pResult").append("<span>options after extend:" + $.toObjectString(options) + "</span>").append("<br/>"); }); $("#go2").click(function(event) { $("#pResult").html(""); var defaults = { validate: false, limit: 5, name: "foo" }; var options = { validate: true, name: "bar" }; $("#pResult").append("<span>defaults:" + $.toObjectString(defaults) + "</span>").append("<br/>"); $("#pResult").append("<span>options:" + $.toObjectString(options) + "</span>").append("<br/>"); var settings = jQuery.extend(defaults, options); $("#pResult").append("<span>settings after extend:" + $.toObjectString(settings) + "</span>").append("<br/>"); $("#pResult").append("<span>defaults after extend:" + $.toObjectString(defaults) + "</span>").append("<br/>"); $("#pResult").append("<span>options after extend:" + $.toObjectString(options) + "</span>").append("<br/>"); }); }); </script></head><body> <button id="go1" style="height:40px;width:400px;"> jQuery.extend(empty, defaults, options)</button> <button id="go2" style="height:40px;width:400px;"> jQuery.extend(defaults, options)</button> <br /> <p id="pResult"> </p></body></html>
结果:
测试工具函数主要用于判断对象是否是某一种类型, 返回的都是Boolean值:
jQuery.isArray( obj )
jQuery.isFunction( obj )
同时别忘记了javascript中自带的isNaN和isFinite:
var test = "123"; alert(isNaN(test)); alert(isFinite(test));
isNaN函数判断参数是否是非数字. 如果是数字则返回false.
isFinite函数检查其参数是否是无穷大.如果参数是 NaN(非数字),或者是正、负无穷大的数,则返回 false.否则返回true.
目前核心类库中只有一个字符串工具函数:
jQuery.trim( str )
返回值: string
说明:去掉字符串起始和结尾的空格。
举例:
去掉字符串起始和结尾的空格:
$.trim(" hello, how are you? ");
结果:
"hello, how are you?"
jQuery.param( obj )
返回值:string
说明:
将表单元素数组或者对象序列化。是.serialize()的核心方法。
数组或jQuery对象会按照name/value对进行序列化,普通对象按照key/value对进行序列化
举例:
var params = { width:1680, height:1050 }; var str = jQuery.param(params); $("#results").text(str);
结果:
width=1680&height=1050
jQuery将其归为Urls分类, 因为此方法通常用于发送GET请求时将对象作为urls参数传递给服务端.
扩展工具函数只需要对jQuery(即"$")进行扩展. 通常开发工具函数或者插件的人希望在开发时使用"$", 但因为"$"有可能和其他脚本库冲突, 所以通常我们使用下面的语法开发工具函数:
(function($) { $.myExtendMethod = function(o) { alert(0); }; })(jQuery);
在函数体内的"$"能保证是代表jQuery对象.
然后使用这种方式开发不能享受到智能感知的便利. 一般我们将扩展工具函数和扩展jQuery包装集函数都放在一个单独的文件中.
下面这个示例演示如何添加自定义的jQuery工具方法和jQuery包装集方法:
/// <reference path="jquery-1.3.2-vsdoc2.js" />jQuery.myExtendMethod = function(o) { /// <summary> /// 扩展方法注释. /// </summary> /// <param name="o" type="String">参数提示文字</param> /// <returns type="string" >返回值提示文字</returns> alert(0); }; jQuery.fn.myExtendMethod = function(o) { /// <summary> /// 扩展方法注释. /// </summary> /// <param name="o" type="String">参数提示文字</param> /// <returns type="string" >返回值提示文字</returns> alert(0); };
透過第一行reference, 我們可以在此js檔案中繼續使用jQuery腳本智慧感知.
#jQuery.myExtendMethod方法擴充的工具函數.
jQuery.fn.myExtendMethod方法擴展的是jQuery包裝集函數, 即為使用$()獲取到的對象添加了方法.
#同理使用XML註釋, 例如
使用.NET中的XML註解(一) -- XML註解標籤講解
jQuery提供了許多的工具函數, 在一般情況下可以滿足我們的需要. 但是對於像JSON格式化一類的操作, 需要我們自己擴展, 現有的各種擴展組件資源將提高我們的開發效率, 本系列Ajax章節就介紹的一個JSON序列化的組件jQuery.json. 更多的組件需要大家在工作中挖掘.
以上是從零開始學習jQuery工具函數的詳細內容。更多資訊請關注PHP中文網其他相關文章!