關於jQuery的
入門使用jQuery可以很容易或具有挑戰性的,這取決於你如何使用JavaScript,HTML,CSS進行開發和編程。
要知道一件重要的事情是,jQuery是只是一個JavaScript庫。jQuery的所有功能特性都是通過JavaScript訪問,所以要對javascript足夠的理解,並能使其構建和調試代碼是必不可少。雖然使用jQuery定期工作可以隨着時間的推移,提高使用JavaScript的熟練程度,可能沒有JavaScript的內置結構和語法的應用知識寫jQuery很難上手。因此,如果你是新來的JavaScript,我們建議您查看的JavaScript基礎教程 Mozilla開發者網絡(MDN)上,想了解jquery的具體javascript實現原理可去http://youmightnotneedjquery.com/
如何jQuery的工作原理
jQuery的:基礎知識
這是一個基本的教程,旨在幫助您使用jQuery上手。如果你沒有一個測試頁面設置呢,通過創建以下的HTML頁面開始:
1
2
3
4
五
6
7
8
9
10
11
12
13
14
15
16
|
<!doctype html>
<html>
<head>
<meta charset="utf-8">
<title>Demo</title>
</head>
<body>
<a href="http://jquery.com/">jQuery</a>
<script src="jquery.js"></script>
<script>
// Your code goes here.
</script>
</body>
</html>
|
該src
屬性中的<script>
元素必須指向jQuery的副本。從下載的jQuery的副本下載jQuery的頁面和存儲jquery.js
文件在同一目錄作為您的HTML文件。
jquery-x.y.z.js
。請確保該文件或者重命名
jquery.js
或更新
src
的屬性
<script>
相匹配的文件名元素。
文檔准備啟動代碼
為了確保他們的代碼運行在瀏覽器完成加載該文件,許多JavaScript程序員包裝自己的代碼在后的onload
功能:
1
2
3
4
五
|
window.onload = function() {
alert( "welcome" );
};
|
不幸的是盡快運行代碼的文件已准備好進行操作,代碼不運行,直到所有圖像都下載完畢,包括橫幅廣告。jQuery ready事件:
1
2
3
4
五
|
$( document ).ready(function() {
// Your code here.
});
|
window
調用的對象
jQuery
和
$
,
$
是一個簡單的別名
jQuery
,它的經常使用,因為它是更短,更快地寫。
例如,在里面ready
時,你可以添加一個單擊處理程序的鏈接:
1
2
3
4
五
6
7
8
9
|
$( document ).ready(function() {
$( "a" ).click(function( event ) {
alert( "Thanks for visiting!" );
});
});
|
上面的jQuery代碼復制到你的HTML文件,它說// Your code goes here
。然后,保存您的HTML文件,然后在瀏覽器中刷新測試頁。點擊鏈接現在應該先顯示一個警告彈出,然后繼續導航到的默認行為http://jquery.com。
對於click
大部分其他的事件,您可以通過調用阻止默認行為event.preventDefault()
的事件處理程序:
1
2
3
4
五
6
7
8
9
10
11
|
$( document ).ready(function() {
$( "a" ).click(function( event ) {
alert( "As you can see, the link no longer took you to jquery.com" );
event.preventDefault();
});
});
|
嘗試更換您的jQuery代碼,先前復制到您的HTML文件中第一個片段,與上面的之一。再次保存HTML文件並重新加載嘗試一下。
完整的示例
下面的例子說明點擊上面的處理代碼的討論,直接在HTML嵌入<body>
。注意,在實踐中,它通常是最好將代碼在一個單獨的JS文件並加載它與在頁面上<script>
的元素的src
屬性。
1
2
3
4
五
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
|
<!doctype html>
<html>
<head>
<meta charset="utf-8">
<title>Demo</title>
</head>
<body>
<a href="http://jquery.com/">jQuery</a>
<script src="jquery.js"></script>
<script>
$( document ).ready(function() {
$( "a" ).click(function( event ) {
alert( "The link will no longer take you to jquery.com" );
event.preventDefault();
});
});
</script>
</body>
</html>
|
添加和刪除一個HTML類
ready
事件,這樣,當文檔准備工作在你的代碼執行。
另一種常見的任務就是添加或刪除類。
首先,添加一些樣式信息寫入<head>
文件,像這樣的:
2
3
4
五
|
<style>
a.test {
font-weight: bold;
}
</style>
|
接下來,添加.addClass()調用腳本:
1
|
$( "a" ).addClass( "test" );
|
所有的<a>
元素現在字體加粗。
要刪除現有類中,使用.removeClass() :
1
|
$( "a" ).removeClass( "test" );
|
特效
jQuery的也提供了一些方便的效果,以幫助您使您的網站脫穎而出。例如,如果你創建一個click處理函數:
1
2
3
4
五
6
7
|
$( "a" ).click(function( event ) {
event.preventDefault();
$( this ).hide( "slow" );
});
|
然后單擊時慢慢鏈接消失。
回調和函數
不像許多其他編程語言,JavaScript的,可以自由地繞過功能在稍后的時間執行。一個回調是作為參數傳遞給另一個函數傳遞與其父功能完成后執行的函數。回調是特殊的,因為他們耐心地等待執行,直到他們的父母完成。同時,瀏覽器可以執行其它功能或做其他各種的工作。
要使用回調,要知道如何將它們傳遞到它們的父功能是非常重要的。
回調不爭論
如果回調沒有參數,你可以將它傳遞這樣的:
1
|
$.get( "myhtmlpage.html", myCallBack );
|
當$獲得()完獲取的頁面myhtmlpage.html
,它執行myCallBack()
的功能。
- 注:這里的第二個參數是簡單的函數名稱(而不是作為一個字符串,而沒有括號)。
回調與參數
帶參數執行回調可能會非常棘手。
錯誤
此代碼示例將無法正常工作:
1
|
$.get( "myhtmlpage.html", myCallBack( param1, param2 ) );
|
失敗的原因是,代碼執行myCallBack( param1, param2 )
立即,然后通過myCallBack()
的返回值作為第二個參數$.get()
。實際上,我們希望傳遞給函數myCallBack()
,而不是myCallBack( param1, param2 )
的返回值(這可能是也可能不是一個函數)。那么,如何傳遞myCallBack()
和包括它的參數?
推遲執行myCallBack()
其參數,你可以使用匿名函數作為包裝。使用注意事項function() {
。匿名函數正是一件事:通話myCallBack()
,用的價值觀param1
和param2
。
1
2
3
4
五
|
$.get( "myhtmlpage.html", function() {
myCallBack( param1, param2 );
});
|
當$.get()
完成后獲得的頁面myhtmlpage.html
,它執行的匿名函數,該函數執行myCallBack( param1, param2 )
。
優化選擇器
選擇器的使用是對性能有很大的考驗,所以在使用選擇器的時候需要小心了。
jQuery的擴展
如果可能的話,應避使用jQuery的擴展選擇器。這些擴展不能利用由本機提供的性能提升的querySelectorAll()
DOM方法,因此,需要使用的jQuery提供的選擇器引擎。
1
2
3
4
五
|
// Slower (the zero-based :even selector is a jQuery extension)
$( "#my-table tr:even" );
// Better, though not exactly equivalent
$( "#my-table tr:nth-child(odd)" );
|
請記住,很多jQuery的擴展,包括:even
在上面的例子中,沒有在CSS規范內。在某些情況下,這些擴展的便利性可能超過其性能成本。
避免過度特異性
1
2
3
4
|
$( ".data table.attendees td.gonzalez" );
// Better: Drop the middle if possible.
$( ".data td.gonzalez" );
|
一個“簡介的”DOM也有助於提高性能的選擇,因為選擇器引擎有更少的層尋找一個跨度的元素。
基於ID選擇器
一個id選擇器有一定的安全性。
1
2
3
4
五
|
// Fast:
$( "#container div.robotarm" );
// Super-fast:
$( "#container" ).find( "div.robotarm" );
|
與第一種方法相比,jQuery的查詢使用DOM document.querySelectorAll()
。第二個例子中,jQuery使用document.getElementById()
,這是更快。
提示舊的瀏覽器
當舊的瀏覽器,如Internet Explorer 8和下方支撐,是必要的,請考慮以下建議:
特異性
選擇器的左右側
1
2
3
4
五
|
// Unoptimized:
$( "div.data .gonzalez" );
// Optimized:
$( ".data td.gonzalez" );
|
使用tag.class
如果可能的話放選擇器的最右邊,只是標簽或只.class在選擇器的最左邊
。
避免通用選擇
通配符選擇雖然會減少代碼做更多事情 ,但是效率很低。
1
2
3
4
五
6
|
$( ".buttons > *" ); // Extremely expensive.
$( ".buttons" ).children(); // Much better.
$( ":radio" ); // Implied universal selection.
$( "*:radio" ); // Same thing, explicit now.
$( "input:radio" ); // Much better.
|
代碼組織概念
當你超越添加簡單的改進自己的網站使用jQuery並開始制定全面的客戶端應用程序,你需要考慮如何組織你的代碼。在本章中,我們將看看你可以在你的jQuery應用程序中使用的各種代碼的組織模式和探索RequireJS依賴管理和構建系統。
關鍵概念
之前,我們跳進代碼的組織模式,了解一些概念是所有好的代碼的組織模式是很重要的。
- 您的代碼應分為功能單位-模塊,服務等,因此要避免把所有的代碼在一個巨大的
$( document ).ready()
塊。這個概念,松散的,被稱為封裝。 - 不要重復自己。找出相似的功能塊之間,並使用繼承技術,以避免重復的代碼。
- 盡管jQuery的DOM為中心的性質,JavaScript應用程序是不是所有的DOM。請記住,不是所有的功能塊需要 - 或者應該 - 有一個DOM表示。
- 功能單位應松耦合,即,功能單元應該能夠在其自己的存在,和單元之間的通信應經由消息收發系統,諸如自定義事件或發布/訂閱處理。功能單元之間保持直接溝通遠只要有可能。
松散耦合的概念可能是特別麻煩的開發人員使他們的第一次涉足復雜的應用程序,從而為您開始留心這一點。
封裝
第一步代碼組織分離您的應用程序為不同的組件; 有時,甚至只是這方面的做的好才滿足開發需要。
對象常量
一個對象字面也許是封裝相關的代碼最簡單的方法。它不提供屬性或方法的任何隱私的,但它是消除匿名函數從代碼中,集中的配置選項,並簡化重用和重構的路徑非常有用。
1
2
3
4
五
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
|
// An object literal
var myFeature = {
myProperty: "hello",
myMethod: function() {
console.log( myFeature.myProperty );
},
init: function( settings ) {
myFeature.settings = settings;
},
readSettings: function() {
console.log( myFeature.settings );
}
};
myFeature.myProperty === "hello"; // true
myFeature.myMethod(); // "hello"
myFeature.init({
foo: "bar"
});
myFeature.readSettings(); // { foo: "bar" }
|
對象上面的文字簡直是分配給一個變量的對象。對象具有一個屬性和幾種方法。所有屬性和方法都是公開的,因此您的應用程序的任何部分可以看到該對象的屬性和調用方法。雖然有一個init方法,沒有什么需要之前的對象是功能,它被調用。
我們如何應用此模式jQuery代碼?比方說,我們有這個代碼寫在傳統的jQuery風格:
1
2
3
4
五
6
7
8
9
10
11
12
|
// Clicking on a list item loads some content using the
// list item's ID, and hides content in sibling list items
$( document ).ready(function() {
$( "#myFeature li" ).append( "<div>" ).click(function() {
var item = $( this );
var div = item.find( "div" );
div.load( "foo.php?item=" + item.attr( "id" ), function() {
div.show();
item.siblings().find( "div" ).hide();
});
});
});
|
如果這是我們的應用程序的范圍,這樣的應用是不好的。在另一方面,如果這是一塊更大的應用程序中,我們會做的很好,保持這個功能不相關的功能分開。我們可能還需要移動URL出代碼,並成為一個配置區域。最后,我們可能要提取鏈接地址,使其更容易為以后修改的功能塊。
1
2
3
4
五
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
三十
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
|
// Using an object literal for a jQuery feature
var myFeature = {
init: function( settings ) {
myFeature.config = {
items: $( "#myFeature li" ),
container: $( "<div class='container'></div>" ),
urlBase: "/foo.php?item="
};
// Allow overriding the default config
$.extend( myFeature.config, settings );
myFeature.setup();
},
setup: function() {
myFeature.config.items
.each( myFeature.createContainer )
.click( myFeature.showItem );
},
createContainer: function() {
var item = $( this );
var container = myFeature.config.container
.clone()
.appendTo( item );
item.data( "container", container );
},
buildUrl: function() {
return myFeature.config.urlBase + myFeature.currentItem.attr( "id" );
},
showItem: function() {
myFeature.currentItem = $( this );
myFeature.getContent( myFeature.showContent );
},
getContent: function( callback ) {
var url = myFeature.buildUrl();
myFeature.currentItem.data( "container" ).load( url, callback );
},
showContent: function() {
myFeature.currentItem.data( "container" ).show();
myFeature.hideContent();
},
hideContent: function() {
myFeature.currentItem.siblings().each(function() {
$( this ).data( "container" ).hide();
});
}
};
$( document ).ready( myFeature.init );
|
你會注意到的第一件事是,這種做法顯然比原來要長 - 再次,如果這是我們的應用程序的范圍,使用對象文本很可能是矯枉過正。假設這不是我們的應用程序的范圍,雖然,我們已經獲得了幾件事情:
- 我們已經打破我們的功能成微小的方法。在未來,如果我們想改變內容的顯示方式,很明顯的地方去改變它。在最初的代碼中,這一步是更難找到。
- 我們已經消除了使用匿名函數。
- 我們已經搬出了代碼的主體配置選項,並把它們在一個中央位置。
- 我們已經消除了鏈條的制約,使代碼更易於重構,重新混音和重新排列。
對於重要的功能,對象文本一條長長的代碼明顯改善$( document ).ready()
塊,因為他們讓我們思考我們的功能塊。然而,他們不是一大堆不僅僅是具有內部一堆函數聲明更先進的$( document ).ready()
塊。
模塊模式
模塊模式克服一些對象的文字的限制,提供變量和函數的隱私,同時如果需要的話曝光公共API。
1
2
3
4
五
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
|
// The module pattern
var feature = (function() {
// Private variables and functions
var privateThing = "secret";
var publicThing = "not secret";
var changePrivateThing = function() {
privateThing = "super secret";
};
var sayPrivateThing = function() {
console.log( privateThing );
changePrivateThing();
};
// Public API
return {
publicThing: publicThing,
sayPrivateThing: sayPrivateThing
};
})();
feature.publicThing; // "not secret"
// Logs "secret" and changes the value of privateThing
feature.sayPrivateThing();
|
在上面的例子中,我們自執行返回的對象的匿名函數。里面的功能,我們定義了一些變量。因為變量的函數的內部定義,我們不具有的功能的外部訪問它們,除非我們把它們返回的對象。這意味着函數以外沒有代碼訪問該privateThing
變量或往changePrivateThing
功能。不過,sayPrivateThing
也有機會獲得privateThing
和changePrivateThing
,因為兩人都在同一范圍定義sayPrivateThing
。
這種模式是強大的,因為你可以從變量名聚集,它可以給你私人的變量和函數同時揭露包括返回的對象的屬性和方法的有限的API。
下面是前面的例子的修訂版本,展示我們可以如何使用模塊模式,而只有露出模塊的一個公共方法創建相同的功能,showItemByIndex()
。
1
2
3
4
五
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
三十
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
|
// Using the module pattern for a jQuery feature
$( document ).ready(function() {
var feature = (function() {
var items = $( "#myFeature li" );
var container = $( "<div class='container'></div>" );
var currentItem = null;
var urlBase = "/foo.php?item=";
var createContainer = function() {
var item = $( this );
var _container = container.clone().appendTo( item );
item.data( "container", _container );
};
var buildUrl = function() {
return urlBase + currentItem.attr( "id" );
};
var showItem = function() {
currentItem = $( this );
getContent( showContent );
};
var showItemByIndex = function( idx ) {
$.proxy( showItem, items.get( idx ) );
};
var getContent = function( callback ) {
currentItem.data( "container" ).load( buildUrl(), callback );
};
var showContent = function() {
currentItem.data( "container" ).show();
hideContent();
};
var hideContent = function() {
currentItem.siblings().each(function() {
$( this ).data( "container" ).hide();
});
};
items.each( createContainer ).click( showItem );
return {
showItemByIndex: showItemByIndex
};
})();
feature.showItemByIndex( 0 );
});
|
當心匿名函數
無處不在的約束匿名函數是一種痛苦。他們是難以調試,維護,測試或重用。相反,使用對象文本來組織和命名您的處理程序和回調。
1
2
3
4
五
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
三十
31
32
33
34
|
// BAD
$( document ).ready(function() {
$( "#magic" ).click(function( event ) {
$( "#yayeffects" ).slideUp(function() {
// ...
});
});
$( "#happiness" ).load( url + " #unicorns", function() {
// ...
});
});
// BETTER
var PI = {
onReady: function() {
$( "#magic" ).click( PI.candyMtn );
$( "#happiness" ).load( PI.url + " #unicorns", PI.unicornCb );
},
candyMtn: function( event ) {
$( "#yayeffects" ).slideUp( PI.slideCb );
},
slideCb: function() { ... },
unicornCb: function() { ... }
};
$( document ).ready( PI.onReady );
|
使用CDN的好處
有幾個原因,一個CDN可以受益您的網站和公司。
1.不同域
的瀏覽器限制並發連接(文件下載)到單個域的數量。大多數允許四個活動連接,因此第五下載被阻塞,直到以前的文件中的一個已經完全恢復。你經常可以看到這個限制的行動來自同一個站點下載多個大文件時。
CDN文件駐留在不同的域。實際上,單個CDN允許瀏覽器的同時下載一個進一步的四個文件。
2.文件可以預先緩存
jQuery是在網絡上無處不在。有一個高概率有人訪問您網站已經訪問了使用谷歌CDN的網站。因此,該文件已經被緩存的瀏覽器和將無需再次下載。
3.高容量的基礎設施,
你可能有很大的主機,但我敢打賭,它沒有被谷歌,微軟或雅虎提供的容量或可擴展性。更好的CDN提供更高的可用性,降低網絡延時,降低丟包。
4.分布式數據中心,
如果你的主要的Web服務器是基於在達拉斯,從歐洲或亞洲的用戶,當他們訪問您的文件必須做出一些跨大陸電子跳。許多的CDN提供局部數據中心,這些中心是更接近用戶,並導致更快的下載。
5.內置版本控制
,通常有可能鏈接到一個CSS文件或JavaScript庫的具體版本。如果需要,可以經常要求“最新”版本。
6.使用分析
許多商業的CDN提供的文件使用情況的報告,因為他們一般每字節充電。這些報告可以補充自己的網站分析和在某些情況下,可以提供視頻觀看和下載一個更好的印象。
7.提高性能和節省資金
CDN的可分配負載,節省帶寬,提高性能並降低現有的托管費用-通常是免費的。