AJAX
開發簡略
文檔說明
|
åƒèˆ‡äººå“¡ï¼š
作者
|
網å
|
è¯çµ¡
|
柯自è°
|
eamoi educhina
|
eamoi@163.com (技術) zcke0728@hotmail.com (版權)
|
|
|
|
發布記錄:
版本
|
日期
|
作者
|
說明
|
1.0
|
<chsdate w:st="on" isrocdate="False" islunardate="False" day="28" month="10" year="2005"><span lang="EN-US" style="FONT-FAMILY: 宋體">2005-10-28</span></chsdate>
|
柯自è°
|
創建,第一版
|
|
|
|
|
éˆæŽ¥ï¼š
類別
|
網å€
|
Blog
|
http://www.blogjava.net/eamoi/
|
MSN-Space
|
http://spaces.msn.com/members/eamoi/
|
OpenDoc 版權說明:
本文檔版權æ¸åŽŸä½œè€…所有。
在å…è²»ã€ä¸”ç„¡ä»»ä½•é™„åŠ æ¢ä»¶çš„å‰æ下,å¯åœ¨ ç¶²çµ¡åª’é«”ä¸ è‡ªç”±å‚³æ’。
如需部分或者全文引用,請事先å¾æ±‚作者æ„見。
如果本文å°æ‚¨æœ‰äº›è¨±å¹«åŠ©ï¼Œè¡¨é”è¬æ„的最好方å¼ï¼Œæ˜¯å°‡æ‚¨ç™¼ç¾çš„å•é¡Œå’Œæ–‡æª”改進æ„見åŠæ™‚å饋給作者。當然,倘若有時間和能力,能為技術群體無償貢ç»è‡ªå·±çš„所å¸ç‚ºæœ€å¥½çš„回饋。
AJAX 開發簡略
一ã€AJAX 定義
二ã€ç¾ç‹€èˆ‡éœ€è¦è§£æ±ºçš„å•é¡Œ
三ã€ç‚ºä»€ä¹ˆä½¿ç”¨AJAX
å››ã€èª°åœ¨ä½¿ç”¨AJAX
五ã€ç”¨AJAX æ”¹é€²ä½ çš„è¨è¨ˆ
例å1 ï¼šæ•¸æ“šæ ¡é©—
例å2 :按需å–數據— ç´šè¯èœå–®
例å3 :讀å–外部數據
å…ã€AJAX 的缺陷
七ã€AJAX 開發
7.1 ã€AJAX 應用到的技術
A ã€XMLHttpRequest å°è±¡
B ã€Javascript
C ã€DOM
D ã€XML
7.2 ã€AJAX 開發框架
A ã€åˆå§‹åŒ–å°è±¡å¹¶ç™¼å‡ºXMLHttpRequest 請求
B ã€æŒ‡å®šéŸ¿æ‡‰è™•ç†å‡½æ•¸
C ã€ç™¼å‡ºHTTP 請求
D ã€è™•ç†æœå‹™å™¨è¿”回的信æ¯
E ã€ä¸€å€‹åˆæ¥çš„開發框架
7.3 ã€ç°¡å–®çš„示例
A ã€æ•¸æ“šæ ¡é©—
B ã€ç´šè¯èœå–®
åƒè€ƒæ–‡ç« :
在使用ç€è¦½å™¨ç€è¦½ç¶²é 的時候,當é é¢åˆ·æ–°å¾ˆæ…¢çš„æ™‚å€™ï¼Œä½ çš„ç€è¦½å™¨åœ¨å¹²ä»€ä¹ˆï¼Ÿä½ çš„å±å¹•å…§å®¹æ˜¯ä»€ä¹ˆï¼Ÿæ˜¯çš„ï¼Œä½ çš„ç€è¦½å™¨åœ¨ç‰å¾…åˆ·æ–°ï¼Œè€Œä½ çš„å±å¹•å…§å®¹æ˜¯ä¸€ç‰‡ç©ºç™½ï¼Œè€Œä½ 在å±å¹•å‰è‹¦è‹¦çš„ç‰å¾…ç€è¦½å™¨çš„響應。開發人員為了克æœé€™ç¨®å°·å°¬çš„å±€é¢ï¼Œä¸å¾—ä¸åœ¨æ¯ä¸€å€‹å¯èƒ½éœ€è¦é•·æ™‚é–“ç‰å¾…響應的é é¢ä¸Šå¢žåŠ 一個 DIV ,告訴用戶“系統æ£åœ¨è™•ç†æ‚¨çš„請求,請ç¨å€™ …… â€ã€‚
ç¾åœ¨ï¼Œæœ‰ä¸€ç¨®è¶Šä¾†è¶Šæµè¡Œè¶Šç†±çš„“è€â€æŠ€è¡“,å¯ä»¥å¾¹åº•æ”¹è®Šé€™ç¨®çª˜è¿«çš„å±€é¢ã€‚那就是 AJAX 。如今,隨著 Gmail 〠Google-maps 的應用和å„種ç€è¦½å™¨çš„支æŒï¼Œ AJAX æ£é€æ¼¸å¸å¼•å…¨ä¸–界的眼çƒã€‚
一ã€
AJAX
定義
AJAX ( Asynchronous JavaScript and XML )其實是多種技術的綜åˆï¼ŒåŒ…括 Javascript 〠XHTML å’Œ CSS 〠DOM 〠XML å’Œ XSTL 〠XMLHttpRequest 。其ä¸ï¼š
使用 XHTML å’Œ CSS 標準化呈ç¾ï¼Œä½¿ç”¨ DOM 實ç¾å‹•æ…‹é¡¯ç¤ºå’Œäº¤äº’,使用 XML å’Œ XSTL 進行數據交æ›èˆ‡è™•ç†ï¼Œä½¿ç”¨ XMLHttpRequest å°è±¡é€²è¡Œç•°æ¥æ•¸æ“šè®€å–,使用 Javascript ç¶å®šå’Œè™•ç†æ‰€æœ‰æ•¸æ“šã€‚
在 AJAX æ出之å‰ï¼Œæ¥ç•Œå°äºŽä¸Šè¿°æŠ€è¡“都åªæ˜¯å–®ç¨çš„使用,沒有綜åˆä½¿ç”¨ï¼Œä¹Ÿæ˜¯ç”±äºŽä¹‹å‰çš„技術需求所決定的。隨著應用的廣泛, AJAX 也æˆç‚ºé¦™é¤‘餑了。
二ã€ç¾ç‹€èˆ‡éœ€è¦è§£æ±ºçš„å•é¡Œ
傳統的
Web
應用采用åŒæ¥äº¤äº’éŽç¨‹ï¼Œé€™ç¨®æƒ…æ³ä¸‹ï¼Œç”¨æˆ¶é¦–å…ˆå‘
HTTP
æœå‹™å™¨è§¸ç™¼ä¸€å€‹è¡Œç‚ºæˆ–請求的呼求。åéŽä¾†ï¼Œæœå‹™å™¨åŸ·è¡ŒæŸäº›ä»»å‹™ï¼Œå†å‘發出請求的用戶返回一個
HTML
é é¢ã€‚這是一種ä¸é€£è²«çš„用戶體驗,æœå‹™å™¨åœ¨è™•ç†è«‹æ±‚的時候,用戶多數時間處于ç‰å¾…的狀態,å±å¹•å…§å®¹ä¹Ÿæ˜¯ä¸€ç‰‡ç©ºç™½ã€‚如下圖:
自從采用超文本作為 Web 傳輸和呈ç¾ä¹‹åŽï¼Œæˆ‘們都是采用這么一套傳輸方å¼ã€‚ç•¶è² è¼‰æ¯”è¼ƒå°çš„時候,這并ä¸æœƒé«”ç¾å‡ºæœ‰ä»€ä¹ˆä¸å¦¥??墒钱斬撦d比較大,響應時間è¦å¾ˆé•·ï¼Œ 1 分é˜ã€ 2 åˆ†é˜ â€¦â€¦ 數分é˜çš„時候,這種ç‰å¾…å°±ä¸å¯å¿å—了。嚴é‡çš„,超éŽéŸ¿æ‡‰æ™‚間,æœå‹™å™¨å¹²è„†å‘Šè¨´ä½ é é¢ä¸å¯ç”¨ã€‚å¦å¤–,æŸäº›æ™‚候,我åªæ˜¯æƒ³æ”¹è®Šé é¢ä¸€å°éƒ¨åˆ†çš„æ•¸æ“šï¼Œé‚£ç‚ºä»€ä¹ˆæˆ‘å¿…é ˆé‡æ–°åŠ 載整個é é¢å‘¢ï¼Ÿï¼ç•¶è»Ÿä»¶è¨è¨ˆè¶Šä¾†è¶Šè¬›ç©¶äººæ€§åŒ–的時候,這么糟糕的用戶體驗簡直與這種原則背é“而馳。為什么è€æ˜¯è¦è®“用戶ç‰å¾…æœå‹™å™¨å–數據呢?至少,我們應該減少用戶ç‰å¾…的時間?,F在,除了程åºè¨è¨ˆã€ç·¨ç¢¼å„ªåŒ–å’Œæœå‹™å™¨èª¿å„ªä¹‹å¤–,還å¯ä»¥é‡‡ç”¨ AJAX 。
三ã€ç‚ºä»€ä¹ˆä½¿ç”¨
AJAX
與傳統的
Web
應用ä¸åŒï¼Œ
AJAX
采用異æ¥äº¤äº’éŽç¨‹ã€‚
AJAX
在用戶與æœå‹™å™¨ä¹‹é–“引入一個ä¸é–“媒介,從而消除了網絡交互éŽç¨‹ä¸çš„處ç†â€”ç‰å¾…—處ç†â€”ç‰å¾…缺點。用戶的ç€è¦½å™¨åœ¨åŸ·è¡Œä»»å‹™æ™‚å³è£è¼‰äº†
AJAX
引擎。
AJAX
引擎用
JavaScript
語言編寫,通常è—在一個隱è—的框架ä¸ã€‚å®ƒè² è²¬ç·¨è¯ç”¨æˆ¶ç•Œé¢åŠèˆ‡æœå‹™å™¨ä¹‹é–“的交互。
AJAX
引擎å…許用戶與應用軟件之間的交互éŽç¨‹ç•°æ¥é€²è¡Œï¼Œç¨ç«‹äºŽç”¨æˆ¶èˆ‡ç¶²çµ¡æœå‹™å™¨é–“的交æµ?,F在,å¯ä»¥ç”¨
Javascript
調用
AJAX
引擎來代替產生一個
HTTP
的用戶動作,內å˜ä¸çš„數據編輯ã€é é¢å°Žèˆªã€æ•¸æ“šæ ¡é©—這些ä¸éœ€è¦é‡æ–°è¼‰å…¥æ•´å€‹é é¢çš„需求å¯ä»¥äº¤çµ¦
AJAX
來執行。
使用 AJAX ,å¯ä»¥ç‚º ISP ã€é–‹ç™¼äººå“¡ã€çµ‚端用戶帶來å¯è¦‹çš„便æ·ï¼š
l 減輕æœå‹™å™¨çš„è² æ“”ã€‚ AJAX 的原則是“按需å–數據â€ï¼Œå¯ä»¥æœ€å¤§ç¨‹åº¦çš„減少冗余請求,和響應å°æœå‹™å™¨é€ æˆçš„è² æ“”ã€‚
l 無刷新更新é é¢ï¼Œæ¸›å°‘用戶心ç†å’Œå¯¦éš›çš„ç‰å¾…時間。特別的,當è¦è®€å–大é‡çš„數據的時候,ä¸ç”¨åƒ Reload 那樣出ç¾ç™½å±çš„情æ³ï¼Œ AJAX 使用 XMLHTTP å°è±¡ç™¼é€è«‹æ±‚并得到æœå‹™å™¨éŸ¿æ‡‰ï¼Œåœ¨ä¸é‡æ–°è¼‰å…¥æ•´å€‹é é¢çš„情æ³ä¸‹ç”¨ Javascript æ“作 DOM 最終更新é é¢ã€‚所以在讀å–數據的éŽç¨‹ä¸ï¼Œç”¨æˆ¶æ‰€é¢å°çš„ä¸æ˜¯ç™½å±ï¼Œæ˜¯åŽŸä¾†çš„é é¢å…§å®¹ï¼ˆä¹Ÿå¯ä»¥åŠ 一個 Loading çš„æ示框讓用戶知é“處于讀å–數據éŽç¨‹ï¼‰ï¼Œåªæœ‰ç•¶æ•¸æ“šæŽ¥æ”¶å®Œç•¢ä¹‹åŽæ‰æ›´æ–°ç›¸æ‡‰éƒ¨åˆ†çš„內容。這種更新是瞬間的,用戶幾乎感覺ä¸åˆ°ã€‚
l 帶來更好的用戶體驗。
l å¯ä»¥æŠŠä»¥å‰ä¸€äº›æœå‹™å™¨è² 擔的工作轉å«åˆ°å®¢æˆ¶ç«¯ï¼Œåˆ©ç”¨å®¢æˆ¶ç«¯é–‘置的能力來處ç†ï¼Œæ¸›è¼•æœå‹™å™¨å’Œå¸¶å¯¬çš„è² æ“”ï¼Œç¯€ç´„ç©ºé–“å’Œå¯¬å¸¶ç§Ÿç”¨æˆæœ¬ã€‚
l å¯ä»¥èª¿ç”¨å¤–部數據。
l 基于標準化的并被廣泛支æŒçš„技術,ä¸éœ€è¦ä¸‹è¼‰æ’件或者å°ç¨‹åºã€‚
l 進一æ¥ä¿ƒé€²é é¢å‘ˆç¾å’Œæ•¸æ“šçš„分離。
å››ã€èª°åœ¨ä½¿ç”¨
AJAX
在應用 AJAX 開發上é¢ï¼Œ Google 當ä»ä¸è®“是表率。 Orkut 〠Gmail 〠Google Groups 〠Google Maps 〠Google Suggest éƒ½æ‡‰ç”¨äº†é€™é …æŠ€è¡“ã€‚ Amazon çš„ A9.com æœç´¢å¼•æ“Žä¹Ÿé‡‡ç”¨äº†é¡žä¼¼çš„技術。
微軟也在ç©æ¥µé–‹ç™¼æ›´ç‚ºå®Œå–„çš„ AJAX 應用:它å³å°‡æŽ¨å‡ºä»£è™Ÿç‚º Atlas çš„ AJAX 工具。 Atlas 的功能超越了 AJAX æœ¬èº«ï¼ŒåŒ…æ‹¬æ•´åˆ Visual Studio 的調試功能。å¦å¤–,新的 ASP.NET 控件將使客戶端控件與æœå‹™å™¨ç«¯ä»£ç¢¼çš„æ†ç¶æ›´ç‚ºç°¡ä¾¿ã€‚ Atlas 客戶腳本框架( Atlas Clent Script Framework )也使與網é åŠç›¸é—œé …目的交互更為便利。但 Visual Studio 2005 ä¸å¹¶ä¸åŒ…å«æ¤é …功能。
微軟最近宣布 Atlas 客戶腳本框架將包å«å¦‚ä¸‹å…§å®¹ï¼ˆè©³ç´°è³‡æ–™è«‹è¨ªå• Atlas 計劃網站):
* 一個å¯æ“´å±•çš„æ ¸å¿ƒæ¡†æž¶ï¼Œå®ƒæ·»åŠ äº† JavaScript 功能:如生命åŒæ™‚期管ç†ã€ç¹¼æ‰¿ç®¡ç†ã€å¤šé»žå‚³é€è™•ç†å™¨å’Œç•Œé¢ç®¡ç†ã€‚
* 一個常見功能的基本類庫,有è±å¯Œçš„å—符串處ç†ã€è¨ˆæ™‚器和é‹è¡Œä»»å‹™ã€‚
* 為 HTML é™„åŠ å‹•æ…‹è¡Œç‚ºçš„ç”¨æˆ¶ç•Œé¢æ¡†æž¶ã€‚
* 一組用來簡化æœå‹™å™¨é€£é€šå’Œç¶²çµ¡è¨ªå•çš„ç¶²çµ¡å †æ£§ã€‚
* 一組è±å¯Œçš„用戶界é¢é–‹ç™¼æŽ§ä»¶ï¼Œå¦‚:自動完æˆçš„文本框ã€å‹•ç•«å’Œæ‹–放。
* 處ç†ç€è¦½å™¨è…³æœ¬è¡Œç‚ºå·®ç•°çš„ç€è¦½å™¨å…¼å®¹å±¤é¢ã€‚
典型的,微軟將 AJAX 技術應用在 MSN Space 上é¢ã€‚å¾ˆå¤šäººä¸€ç›´éƒ½å° MS Space æœå‹™æ„Ÿåˆ°å¾ˆå¥‡æ€ªï¼Œç•¶æ交回復評論以åŽï¼Œç€è¦½å™¨æœƒæš«æ™‚åœé “一下,然åŽåœ¨ç„¡åˆ·æ–°çš„情æ³ä¸‹æŠŠæˆ‘æ交的評論顯示出來。這個就是應用了 AJAX çš„æ•ˆæžœã€‚è©¦æƒ³ï¼Œå¦‚æžœæ·»åŠ ä¸€å€‹è©•è«–å°±è¦é‡æ–°åˆ·æ–°æ•´å€‹é é¢ï¼Œé‚£å¯çœŸè²»äº‹ã€‚
ç›®å‰ï¼Œ AJAX 應用最普éçš„é ˜åŸŸæ˜¯ GIS-Map æ–¹é¢ã€‚ GIS çš„å€åŸŸæœç´¢å¼·èª¿å¿«é€ŸéŸ¿æ‡‰ï¼Œ AJAX 的特點æ£å¥½ç¬¦åˆé€™ç¨®éœ€æ±‚。
五ã€ç”¨
AJAX
æ”¹é€²ä½ çš„è¨è¨ˆ
AJAX 雖然å¯ä»¥å¯¦ç¾ç„¡åˆ·æ–°æ›´æ–°é é¢å…§å®¹ï¼Œä½†æ˜¯ä¹Ÿä¸æ˜¯ä»€ä¹ˆåœ°æ–¹éƒ½å¯ä»¥ç”¨ï¼Œä¸»è¦æ‡‰ç”¨åœ¨äº¤äº’較多ã€é »ç¹è®€æ•¸æ“šã€æ•¸æ“šåˆ†é¡žè‰¯å¥½çš„ Web 應用ä¸?,F在,讓我們舉兩個例å,看看如何用 AJAX æ”¹é€²ä½ çš„è¨è¨ˆã€‚
例å
1
ï¼šæ•¸æ“šæ ¡é©—
在輸入 form 表單內容的時候,我們通常需è¦ç¢ºä¿æ•¸æ“šçš„å”¯ä¸€æ€§ã€‚å› æ¤ï¼Œå¸¸å¸¸åœ¨é é¢ä¸Šæä¾›â€œå”¯ä¸€æ€§æ ¡é©—â€æŒ‰éˆ•ï¼Œè®“ç”¨æˆ¶é»žæ“Šï¼Œæ‰“é–‹ä¸€å€‹æ ¡é©—å°çª—å£ï¼›æˆ–è€…ç‰ form æ交到æœå‹™å™¨ç«¯ï¼Œç”±æœå‹™å™¨åˆ¤æ–·åŽåœ¨è¿”å›žç›¸æ‡‰çš„æ ¡é©—ä¿¡æ¯ã€‚å‰è€…, window.open æ“作本來就是比較耗費資æºçš„,通常由 window. showModalDialog 代替,å³ä½¿é€™æ¨£ä¹Ÿè¦å½ˆå‡ºä¸€å€‹å°è©±æ¡†ï¼›åŽè€…,需è¦æŠŠæ•´å€‹é é¢æ交到æœå‹™å™¨å¹¶ç”±æœå‹™å™¨åˆ¤æ–·æ ¡é©—,這個éŽç¨‹ä¸åƒ…æ™‚é–“é•·è€Œä¸”åŠ é‡äº†æœå‹™å™¨è² 擔。而使用 AJAX ï¼Œé€™å€‹æ ¡é©—è«‹æ±‚å¯ä»¥ç”± XMLHttpRequest å°è±¡ç™¼å‡ºï¼Œæ•´å€‹éŽç¨‹ä¸éœ€è¦å½ˆå‡ºæ–°çª—å£ï¼Œä¹Ÿä¸éœ€è¦å°‡æ•´å€‹é é¢æ交到æœå‹™å™¨ï¼Œå¿«é€Ÿåˆä¸åŠ é‡æœå‹™å™¨è² 擔。
例å
2
:按需å–數據
—
ç´šè¯èœå–®
以å‰ï¼Œç‚ºäº†é¿å…æ¯æ¬¡å°èœå–®çš„æ“作引起的é‡è¼‰é é¢ï¼Œä¸é‡‡ç”¨æ¯æ¬¡èª¿ç”¨åŽè‡ºçš„æ–¹å¼ï¼Œè€Œæ˜¯ä¸€æ¬¡æ€§å°‡ç´šè¯èœå–®çš„所有數據全部讀å–出來并寫入數組,然åŽæ ¹æ“šç”¨æˆ¶çš„æ“作用 JavaScript 來控制它的åé›†é …ç›®çš„å‘ˆç¾ï¼Œé€™æ¨£é›–然解決了æ“作響應速度ã€ä¸é‡è¼‰é é¢ä»¥åŠé¿å…å‘æœå‹™å™¨é »ç¹ç™¼é€è«‹æ±‚çš„å•é¡Œï¼Œä½†æ˜¯å¦‚果用戶ä¸å°èœå–®é€²è¡Œæ“作或åªå°èœå–®ä¸çš„一部分進行æ“作的話,那讀å–的數據ä¸çš„一部分就會æˆç‚ºå†—余數據而浪費用戶的資æºï¼Œç‰¹åˆ¥æ˜¯åœ¨èœå–®çµæ§‹å¾©é›œã€æ•¸æ“šé‡å¤§çš„情æ³ä¸‹ï¼ˆæ¯”如èœå–®æœ‰å¾ˆå¤šç´šã€æ¯ä¸€ç´šèœåˆæœ‰ä¸Šç™¾å€‹é …目),這種弊端就更為çªå‡ºã€‚
ç¾åœ¨æ‡‰ç”¨ AJAX ,在åˆå§‹åŒ–é é¢æ™‚我們åªè®€å‡ºå®ƒçš„第一級的所有數據并顯示,在用戶æ“作一級èœå–®å…¶ä¸ä¸€é …æ™‚ï¼Œæœƒé€šéŽ Ajax å‘åŽè‡ºè«‹æ±‚當å‰ä¸€ç´šé …目所屬的二級åèœå–®çš„所有數據,如果å†ç¹¼çºŒè«‹æ±‚已經呈ç¾çš„二級èœå–®ä¸çš„ä¸€é …æ™‚ï¼Œå†å‘åŽé¢è«‹æ±‚所æ“作二級èœå–®é …å°æ‡‰çš„所有三級èœå–®çš„所有數據,以æ¤é¡žæŽ¨â€¦â€¦é€™æ¨£ï¼Œç”¨ä»€ä¹ˆå°±å–什么ã€ç”¨å¤šå°‘å°±å–多少,就ä¸æœƒæœ‰æ•¸æ“šçš„冗余和浪費,減少了數據下載總é‡ï¼Œè€Œä¸”æ›´æ–°é é¢æ™‚ä¸ç”¨é‡è¼‰å…¨éƒ¨å…§å®¹ï¼Œåªæ›´æ–°éœ€è¦æ›´æ–°çš„那部分å³å¯ï¼Œç›¸å°äºŽåŽè‡ºè™•ç†å¹¶é‡è¼‰çš„æ–¹å¼ç¸®çŸäº†ç”¨æˆ¶ç‰å¾…時間,也把å°è³‡æºçš„浪費é™åˆ°æœ€ä½Žã€‚
例å
3
:讀å–外部數據
AJAX å¯ä»¥èª¿ç”¨å¤–éƒ¨æ•¸æ“šï¼Œå› æ¤ï¼Œå¯ä»¥å°ä¸€äº›é–‹ç™¼çš„數據比如 XML 文檔〠RSS æ–‡æª”é€²è¡ŒäºŒæ¬¡åŠ å·¥ï¼Œå¯¦ç¾æ•¸æ“šæ•´åˆæˆ–者開發應用程åºã€‚
å…ã€
AJAX
的缺陷
AJAX ä¸æ˜¯å®Œç¾Žçš„技術。使用 AJAX ,它的一些缺陷ä¸å¾—ä¸æ¬Šè¡¡ä¸€ä¸‹ï¼š
l AJAX 大é‡ä½¿ç”¨äº† Javascript å’Œ AJAX 引擎,而這個å–決于ç€è¦½å™¨çš„支æŒã€‚ IE5.0 åŠä»¥ä¸Šã€ Mozilla1.0 〠NetScape7 åŠä»¥ä¸Šç‰ˆæœ¬æ‰æ”¯æŒï¼Œ Mozilla é›–ç„¶ä¹Ÿæ”¯æŒ AJAX ,但是æä¾› XMLHttpRequest çš„æ–¹å¼ä¸ä¸€æ¨£ã€‚所以,使用 AJAX 的程åºå¿…é ˆæ¸¬è©¦é‡å°å„個ç€è¦½å™¨çš„兼容性。
l AJAX æ›´æ–°é é¢å…§å®¹çš„時候并沒有刷新整個é é¢ï¼Œå› æ¤ï¼Œç¶²é çš„åŽé€€åŠŸèƒ½æ˜¯å¤±æ•ˆçš„;有的用戶還經常æžä¸æ¸…楚ç¾åœ¨çš„數據是舊的還是已經更新éŽçš„。這個就需è¦åœ¨æ˜Žé¡¯ä½ç½®æ醒用戶“數據已更新â€ã€‚
l å°æµåª’體的支æŒæ²’有 FLASH 〠Java Applet 好。
l 一些手æŒè¨å‚™ï¼ˆå¦‚手機〠PDA ç‰ï¼‰ç¾åœ¨é‚„ä¸èƒ½å¾ˆå¥½çš„æ”¯æŒ Ajax 。
七ã€
AJAX
開發
到這里,已經å¯ä»¥æ¸…æ¥šçš„çŸ¥é“ AJAX 是什么, AJAX 能åšä»€ä¹ˆï¼Œ AJAX 什么地方ä¸å¥½ã€‚å¦‚æžœä½ è¦ºå¾— AJAX çœŸçš„èƒ½çµ¦ä½ çš„é–‹ç™¼å·¥ä½œå¸¶ä¾†æ”¹é€²çš„è©±ï¼Œé‚£ä¹ˆç¹¼çºŒçœ‹çœ‹æ€Žä¹ˆä½¿ç”¨ AJAX å§ã€‚
7.1
ã€
AJAX
應用到的技術
AJAX 涉åŠåˆ°çš„ 7 é …æŠ€è¡“ä¸ï¼Œå€‹äººèªç‚º Javascript 〠XMLHttpRequest 〠DOM 〠XML 比較有用。
A
ã€
XMLHttpRequest
å°è±¡
XMLHttpRequest 是 XMLHTTP 組件的å°è±¡ï¼Œé€šéŽé€™å€‹å°è±¡ï¼Œ AJAX å¯ä»¥åƒæ¡Œé¢æ‡‰ç”¨ç¨‹åºä¸€æ¨£åªåŒæœå‹™å™¨é€²è¡Œæ•¸æ“šå±¤é¢çš„交æ›ï¼Œè€Œä¸ç”¨æ¯æ¬¡éƒ½åˆ·æ–°ç•Œé¢ï¼Œä¹Ÿä¸ç”¨æ¯æ¬¡å°‡æ•¸æ“šè™•ç†çš„工作都交給æœå‹™å™¨ä¾†åšï¼›é€™æ¨£æ—¢æ¸›è¼•äº†æœå‹™å™¨è² æ“”åˆåŠ 快了響應速度ã€ç¸®çŸäº†ç”¨æˆ¶ç‰å¾…的時間。
IE5.0 開始,開發人員å¯ä»¥åœ¨ Web é é¢å…§éƒ¨ä½¿ç”¨ XMLHTTP ActiveX 組件擴展自身的功能,ä¸ç”¨å¾žç•¶å‰çš„ Web é é¢å°Žèˆªå°±å¯ä»¥ç›´æŽ¥å‚³è¼¸æ•¸æ“šåˆ°æœå‹™å™¨æˆ–者從æœå‹™å™¨æŽ¥æ”¶æ•¸æ“šã€‚ ,Mozilla1.0 ä»¥åŠ NetScape7 則是創建繼承 XML 的代ç†é¡ž XMLHttpRequest ï¼›å°äºŽå¤§å¤šæ•¸æƒ…æ³ï¼Œ XMLHttpRequest å°è±¡å’Œ XMLHTTP 組件很相似,方法和屬性類似,åªæ˜¯éƒ¨åˆ†å±¬æ€§ä¸åŒã€‚
XMLHttpRequest å°è±¡åˆå§‹åŒ–:
<script language="â€javascriptâ€" type="text/javascript"></script>
var http_request = false;
//IE ç€è¦½å™¨
http_request = new ActiveXObject("Msxml2.XMLHTTP");
http_request = new ActiveXObject("Microsoft.XMLHTTP");
//Mozilla ç€è¦½å™¨
http_request = new XMLHttpRequest();
XMLHttpRequest å°è±¡çš„方法:
方法 |
æè¿° |
abort() |
åœæ¢ç•¶å‰è«‹æ±‚ |
getAllResponseHeaders() |
作為å—符串返回完整的 headers |
getResponseHeader("headerLabel") |
作為å—符串返回單個的 header 標簽 |
open("method","URL"[,asyncFlag[,"userName"[, "password"]]]) |
è¨ç½®æœªæ±ºçš„請求的目標 URL ,方法,和其他åƒæ•¸ |
send(content) |
發é€è«‹æ±‚ |
setRequestHeader("label", "value") |
è¨ç½® header å¹¶å’Œè«‹æ±‚ä¸€èµ·ç™¼é€ |
XMLHttpRequest å°è±¡çš„屬性:
屬性 |
æè¿° |
onreadystatechange |
狀態改變的事件觸發器 |
readyState |
å°è±¡ç‹€æ…‹ (integer): 0 = 未åˆå§‹åŒ– 1 = 讀å–ä¸ 2 = å·²è®€å– 3 = äº¤äº’ä¸ 4 = å®Œæˆ |
responseText |
æœå‹™å™¨é€²ç¨‹è¿”回數據的文本版本 |
responseXML |
æœå‹™å™¨é€²ç¨‹è¿”回數據的兼容 DOM çš„ XML 文檔å°è±¡ |
status |
æœå‹™å™¨è¿”回的狀態碼 , 如: 404 = " 文件未找到 " 〠200 =" æˆåŠŸ " |
statusText |
æœå‹™å™¨è¿”å›žçš„ç‹€æ…‹æ–‡æœ¬ä¿¡æ¯ |
B
ã€
Javascript
Javascript 一直被定ä½ç‚ºå®¢æˆ¶ç«¯çš„è…³æœ¬èªžè¨€ï¼Œæ‡‰ç”¨æœ€å¤šçš„åœ°æ–¹æ˜¯è¡¨å–®æ•¸æ“šçš„æ ¡é©—?,F在,å¯ä»¥é€šéŽ Javascript æ“作 XMLHttpRequest ,來跟數據庫打交é“。
C
ã€
DOM
DOM ( Document Object Model )是æ供給 HTML å’Œ XML 使用的一組 API ,æ供了文件的表述çµæ§‹ï¼Œå¹¶å¯ä»¥åˆ©ç”¨å®ƒæ”¹è®Šå…¶ä¸çš„內容和å¯è¦‹ç‰©ã€‚è…³æœ¬èªžè¨€é€šéŽ DOM æ‰å¯ä»¥è·Ÿé é¢é€²è¡Œäº¤äº’。 Web 開發人員å¯æ“作åŠå»ºç«‹æ–‡ä»¶çš„屬性ã€æ–¹æ³•ä»¥åŠäº‹ä»¶éƒ½ä»¥å°è±¡ä¾†å±•ç¾ã€‚比如, document 就代表é é¢å°è±¡æœ¬èº«ã€‚
D
ã€
XML
é€šéŽ XML ( Extensible Markup Language ),å¯ä»¥è¦èŒƒçš„定義çµæ§‹åŒ–數據,是網上傳輸的數據和文檔符åˆçµ±ä¸€çš„標準。用 XML 表述的數據和文檔,å¯ä»¥å¾ˆå®¹æ˜“的讓所有程åºå…±äº«ã€‚
7.2
ã€
AJAX
開發框架
這里,我們通éŽä¸€æ¥æ¥çš„解æžï¼Œä¾†å½¢æˆä¸€å€‹ç™¼é€å’ŒæŽ¥æ”¶ XMLHttpRequest 請求的程åºæ¡†æž¶ã€‚ AJAX 實質上也是éµå¾ª Request/Server 模å¼ï¼Œæ‰€ä»¥é€™å€‹æ¡†æž¶åŸºæœ¬çš„æµç¨‹ä¹Ÿæ˜¯ï¼šå°è±¡åˆå§‹åŒ– à 發é€è«‹æ±‚ à æœå‹™å™¨æŽ¥æ”¶ à æœå‹™å™¨è¿”回 à 客戶端接收 à 修改客戶端é é¢å…§å®¹ã€‚åªä¸éŽé€™å€‹éŽç¨‹æ˜¯ç•°æ¥çš„。
A
ã€åˆå§‹åŒ–å°è±¡å¹¶ç™¼å‡º
XMLHttpRequest
請求
為了讓
Javascript
å¯ä»¥å‘æœå‹™å™¨ç™¼é€
HTTP
è«‹æ±‚ï¼Œå¿…é ˆä½¿ç”¨
XMLHttpRequest
å°è±¡ã€‚使用之å‰ï¼Œè¦å…ˆå°‡
XMLHttpRequest
å°è±¡å¯¦ä¾‹åŒ–。之å‰èªªéŽï¼Œå„個ç€è¦½å™¨å°é€™å€‹å¯¦ä¾‹åŒ–éŽç¨‹å¯¦ç¾ä¸åŒã€‚
IE
以
ActiveX
控件的形å¼æ供,而
Mozilla
ç‰ç€è¦½å™¨å‰‡ç›´æŽ¥ä»¥
XMLHttpRequest
é¡žçš„å½¢å¼æ供。為了讓編寫的程åºèƒ½å¤ è·¨ç€è¦½å™¨é‹è¡Œï¼Œè¦é€™æ¨£å¯«ï¼š
if (window.XMLHttpRequest) { // Mozilla, Safari, ...
http_request = new XMLHttpRequest();
} else if (window.ActiveXObject) { // IE
http_request = new ActiveXObject("Microsoft.XMLHTTP");
}
有些版本的
Mozilla
ç€è¦½å™¨è™•ç†æœå‹™å™¨è¿”回的未包å«
XML mime-type
é 部信æ¯çš„å…§å®¹æ™‚æœƒå‡ºéŒ¯ã€‚å› æ¤ï¼Œè¦ç¢ºä¿è¿”回的內容包å«
text/xml
ä¿¡æ¯ã€‚
http_request = new XMLHttpRequest();
http_request.overrideMimeType('text/xml');
B
ã€æŒ‡å®šéŸ¿æ‡‰è™•ç†å‡½æ•¸
接下來è¦æŒ‡å®šç•¶æœå‹™å™¨è¿”回信æ¯æ™‚客戶端的處ç†æ–¹å¼ã€‚åªè¦å°‡ç›¸æ‡‰çš„處ç†å‡½æ•¸å稱賦給
XMLHttpRequest
å°è±¡çš„
onreadystatechange
屬性就å¯ä»¥äº†ã€‚比如:
http_request.onreadystatechange = processRequest;
需è¦æŒ‡å‡ºçš„時,這個函數å稱ä¸åŠ 括號,ä¸æŒ‡å®šåƒæ•¸ã€‚也å¯ä»¥ç”¨
Javascript
å³æ™‚定義函數的方å¼å®šç¾©éŸ¿æ‡‰å‡½æ•¸ã€‚比如:
http_request.onreadystatechange = function() {
};
C
ã€ç™¼å‡º
HTTP
請求
指定響應處ç†å‡½æ•¸ä¹‹åŽï¼Œå°±å¯ä»¥å‘æœå‹™å™¨ç™¼å‡º
HTTP
請求了。這一æ¥èª¿ç”¨
XMLHttpRequest
å°è±¡çš„
open
和
send
方法。
http_request.open('GET', 'http://www.example.org/some.file', true);
http_request.send(null);
open 的第一個åƒæ•¸æ˜¯ HTTP 請求的方法,為 Get 〠Post 或者 Head 。
第二個åƒæ•¸æ˜¯ç›®æ¨™ URL ?;诎踩î¼ç´¤],這個 URL åªèƒ½æ˜¯åŒç¶²åŸŸçš„,å¦å‰‡æœƒæ示“沒有權é™â€çš„錯誤。這個 URL å¯ä»¥æ˜¯ä»»ä½•çš„ URL ,包括需è¦æœå‹™å™¨è§£é‡‹åŸ·è¡Œçš„é é¢ï¼Œä¸åƒ…僅是éœæ…‹é é¢ã€‚
第三個åƒæ•¸åªæ˜¯æŒ‡å®šåœ¨ç‰å¾…æœå‹™å™¨è¿”回信æ¯çš„時間內是å¦ç¹¼çºŒåŸ·è¡Œä¸‹é¢çš„代碼。如果為 True ,則ä¸æœƒç¹¼çºŒåŸ·è¡Œï¼Œç›´åˆ°æœå‹™å™¨è¿”回信æ¯ã€‚默èªç‚º True 。
æŒ‰ç…§é †åºï¼Œ open 調用完畢之åŽè¦èª¿ç”¨ send 方法。 send çš„åƒæ•¸å¦‚果是以 Post æ–¹å¼ç™¼å‡ºçš„話,å¯ä»¥æ˜¯ä»»ä½•æƒ³å‚³çµ¦æœå‹™å™¨çš„內容。ä¸éŽï¼Œè·Ÿ form 一樣,如果è¦å‚³æ–‡ä»¶çµ¦æœå‹™å™¨ï¼Œå¿…é ˆå…ˆèª¿ç”¨ setRequestHeader 方法,修改 MIME 類別。如下:
http_request.setRequestHeader(“Content-Typeâ€,â€application/x-www-form-urlencodedâ€);
D
ã€è™•ç†æœå‹™å™¨è¿”回的信æ¯
在第二æ¥æˆ‘們已經指定了響應處ç†å‡½æ•¸ï¼Œé€™ä¸€æ¥ï¼Œä¾†çœ‹çœ‹é€™å€‹éŸ¿æ‡‰è™•ç†å‡½æ•¸éƒ½æ‡‰è©²åšä»€ä¹ˆã€‚
首先,它è¦æª¢æŸ¥ XMLHttpRequest å°è±¡çš„ readyState 值,判斷請求目å‰çš„狀態。åƒç…§å‰æ–‡çš„屬性表å¯ä»¥çŸ¥é“, readyState 值為 4 的時候,代表æœå‹™å™¨å·²ç¶“傳回所有的信æ¯ï¼Œå¯ä»¥é–‹å§‹è™•ç†ä¿¡æ¯å¹¶æ›´æ–°é é¢å…§å®¹äº†ã€‚如下:
if (http_request.readyState == 4) {
// ä¿¡æ¯å·²ç¶“返回,å¯ä»¥é–‹å§‹è™•ç†
} else {
// ä¿¡æ¯é‚„沒有返回,ç‰å¾…
}
æœå‹™å™¨è¿”回信æ¯åŽï¼Œé‚„需è¦åˆ¤æ–·è¿”回的
HTTP
狀態碼,確定返回的é é¢æ²’有錯誤。所有的狀態碼都å¯ä»¥åœ¨
W3C
的官方網站上查到。其ä¸ï¼Œ
200
代表é é¢æ£å¸¸ã€‚
if (http_request.status == 200) {
// é é¢æ£å¸¸ï¼Œå¯ä»¥é–‹å§‹è™•ç†ä¿¡æ¯
} else {
// é é¢æœ‰å•é¡Œ
}
XMLHttpRequest å°æˆåŠŸè¿”回的信æ¯æœ‰å…©ç¨®è™•ç†æ–¹å¼ï¼š
responseText :將傳回的信æ¯ç•¶å—符串使用;
responseXML :將傳回的信æ¯ç•¶ XML 文檔使用,å¯ä»¥ç”¨ DOM 處ç†ã€‚
E
ã€ä¸€å€‹åˆæ¥çš„開發框架
總çµä¸Šé¢çš„æ¥é©Ÿï¼Œæˆ‘們整ç†å‡ºä¸€å€‹åˆæ¥çš„å¯ç”¨çš„開發框架,供以åŽèª¿ç”¨ï¼›é€™é‡Œï¼Œå°‡æœå‹™å™¨è¿”回的信æ¯ç”¨
window.alert
以å—符串的形å¼é¡¯ç¤ºå‡ºä¾†ï¼š
<script language="javascript">
var http_request = false;
function send_request(url) {// åˆå§‹åŒ–ã€æŒ‡å®šè™•ç†å‡½æ•¸ã€ç™¼é€è«‹æ±‚的函數
http_request = false;
// 開始åˆå§‹åŒ– XMLHttpRequest å°è±¡
if(window.XMLHttpRequest) { //Mozilla ç€è¦½å™¨
http_request = new XMLHttpRequest();
if (http_request.overrideMimeType) {// è¨ç½® MiME 類別
http_request.overrideMimeType("text/xml");
}
}
else if (window.ActiveXObject) { // IE ç€è¦½å™¨
try {
http_request = new ActiveXObject("Msxml2.XMLHTTP");
} catch (e) {
try {
http_request = new ActiveXObject("Microsoft.XMLHTTP");
} catch (e) {}
}
}
if (!http_request) { // 異常,創建å°è±¡å¯¦ä¾‹å¤±æ•—
window.alert(" ä¸èƒ½å‰µå»º XMLHttpRequest å°è±¡å¯¦ä¾‹ .");
return false;
}
http_request.onreadystatechange = processRequest;
// 確定發é€è«‹æ±‚çš„æ–¹å¼å’Œ URL 以åŠæ˜¯å¦åŒæ¥åŸ·è¡Œä¸‹æ®µä»£ç¢¼
http_request.open("GET", url, true);
http_request.send(null);
}
// 處ç†è¿”回信æ¯çš„函數
function processRequest() {
if (http_request.readyState == 4) { // 判斷å°è±¡ç‹€æ…‹
if (http_request.status == 200) { // ä¿¡æ¯å·²ç¶“æˆåŠŸè¿”回,開始處ç†ä¿¡æ¯
alert(http_request.responseText);
} else { // é é¢ä¸æ£å¸¸
alert(" 您所請求的é é¢æœ‰ç•°å¸¸ã€‚ ");
}
}
}
</script>
<script language="javascript" type="text/javascript"></script>
var http_request = false;
function send_request(url) {// åˆå§‹åŒ–ã€æŒ‡å®šè™•ç†å‡½æ•¸ã€ç™¼é€è«‹æ±‚的函數
http_request = false;
// 開始åˆå§‹åŒ– XMLHttpRequest å°è±¡
if(window.XMLHttpRequest) { //Mozilla ç€è¦½å™¨
http_request = new XMLHttpRequest();
if (http_request.overrideMimeType) {// è¨ç½® MiME 類別
http_request.overrideMimeType("text/xml");
}
}
else if (window.ActiveXObject) { // IE ç€è¦½å™¨
try {
http_request = new ActiveXObject("Msxml2.XMLHTTP");
} catch (e) {
try {
http_request = new ActiveXObject("Microsoft.XMLHTTP");
} catch (e) {}
}
}
if (!http_request) { // 異常,創建å°è±¡å¯¦ä¾‹å¤±æ•—
window.alert(" ä¸èƒ½å‰µå»º XMLHttpRequest å°è±¡å¯¦ä¾‹ .");
return false;
}
http_request.onreadystatechange = processRequest;
// 確定發é€è«‹æ±‚çš„æ–¹å¼å’Œ URL 以åŠæ˜¯å¦åŒæ¥åŸ·è¡Œä¸‹æ®µä»£ç¢¼
http_request.open("GET", url, true);
http_request.send(null);
}
// 處ç†è¿”回信æ¯çš„函數
function processRequest() {
if (http_request.readyState == 4) { // 判斷å°è±¡ç‹€æ…‹
if (http_request.status == 200) { // ä¿¡æ¯å·²ç¶“æˆåŠŸè¿”回,開始處ç†ä¿¡æ¯
alert(http_request.responseText);
} else { // é é¢ä¸æ£å¸¸
alert(" 您所請求的é é¢æœ‰ç•°å¸¸ã€‚ ");
}
}
}
7.3
ã€ç°¡å–®çš„示例
接下來,我們利用上é¢çš„開發框架來åšå…©å€‹ç°¡å–®çš„應用。
A
ã€æ•¸æ“šæ ¡é©—
在用戶注冊的表單ä¸ï¼Œç¶“常碰到è¦æª¢é©—待注冊的用戶å是å¦å”¯ä¸€ã€‚傳統的åšæ³•æ˜¯é‡‡ç”¨ window.open 的彈出窗å£ï¼Œæˆ–者 window. showModalDialog çš„å°è©±æ¡†ã€‚ä¸éŽï¼Œé€™å…©å€‹éƒ½éœ€è¦æ‰“開窗å£ã€‚采用 AJAX åŽï¼Œé‡‡ç”¨ç•°æ¥æ–¹å¼ç›´æŽ¥å°‡åƒæ•¸æ交到æœå‹™å™¨ï¼Œç”¨ window.alert å°‡æœå‹™å™¨è¿”å›žçš„æ ¡é©—ä¿¡æ¯é¡¯ç¤ºå‡ºä¾†ã€‚代碼如下:
在
ä¹‹é–“å¢žåŠ ä¸€æ®µ
form
表單代碼:
在開發框架的基礎上å†å¢žåŠ 一個調用函數:
function userCheck() {
var f = document.form1;
var username = f.username.value;
if(username=="") {
window.alert(" 用戶åä¸èƒ½ç‚ºç©ºã€‚ ");
f.username.focus();
return false;
}
else {
send_request('sample1_2.jsp?username='+username);
}
}
看看
sample1_2.jsp
åšäº†ä»€ä¹ˆï¼š
<%@ page contentType="text/html; charset=gb2312" errorPage="" %>
<%
String username = request.getParameter("username");
if("educhina".equals(username)) out.print(" 用戶å已經被注冊,請更æ›ä¸€å€‹ç”¨æˆ¶å。 ");
else out.print(" 用戶å尚未被使用,您å¯ä»¥ç¹¼çºŒã€‚ ");
%>
é‹è¡Œä¸€ä¸‹ï¼Œå—¯ï¼Œæ²’有彈出窗å£ï¼Œæ²’有é é¢åˆ·æ–°ï¼Œè·Ÿé 想的效果一樣。如果需è¦çš„話,å¯ä»¥åœ¨ sample1_2.jsp ä¸å¯¦ç¾æ›´å¾©é›œçš„功能。最åŽï¼Œåªè¦å°‡å饋信æ¯æ‰“å°å‡ºä¾†å°±å¯ä»¥äº†ã€‚
B
ã€ç´šè¯èœå–®
我們在第五部分æ到利用 AJAX 改進級è¯èœå–®çš„è¨è¨ˆã€‚接下來,我們就演示一下如何“按需å–數據â€ã€‚
首先,在 <body></body> ä¸é–“å¢žåŠ å¦‚ä¸‹ HTML 代碼:
<table width="200" border="0" cellspacing="0" cellpadding="0">
<tr>
<td height="20">
<a href="javascript:void(0)" onClick="showRoles('pos_1')"> 經ç†å®¤ </a>
</td>
</tr>
<tr style="display:none">
<td height="20" id="pos_1"> </td>
</tr>
<tr>
<td height="20">
<a href="javascript:void(0)" onClick="showRoles('pos_2')"> 開發部 </a>
</td>
</tr>
<tr style="display:none ">
<td id="pos_2" height="20"> </td>
</tr>
</table>
åœ¨æ¡†æž¶çš„åŸºç¤Žä¸Šå¢žåŠ ä¸€å€‹éŸ¿æ‡‰å‡½æ•¸ showRoles(obj) :
// 顯示部門下的崗ä½
function showRoles(obj) {
document.getElementById(obj).parentNode.style.display = "";
document.getElementById(obj).innerHTML = " æ£åœ¨è®€å–數據 ..."
currentPos = obj;
send_request("sample2_2.jsp?playPos="+obj);
}
修改框架的 processRequest 函數:
// 處ç†è¿”回信æ¯çš„函數
function processRequest() {
if (http_request.readyState == 4) { // 判斷å°è±¡ç‹€æ…‹
if (http_request.status == 200) { // ä¿¡æ¯å·²ç¶“æˆåŠŸè¿”回,開始處ç†ä¿¡æ¯
document.getElementById(currentPos).innerHTML = http_request.responseText;
} else { // é é¢ä¸æ£å¸¸
alert(" 您所請求的é é¢æœ‰ç•°å¸¸ã€‚ ");
}
}
}
最åŽå°±æ˜¯ smaple2_2.jsp 了:
<%@ page contentType="text/html; charset=gb2312" errorPage="" %>
<%
String playPos = request.getParameter("playPos");
if("pos_1".equals(playPos))
out.print(" ç¸½ç¶“ç† <br> å‰¯ç¸½ç¶“ç† ");
else if("pos_2".equals(playPos))
out.println(" 總工程師 <br> 軟件工程師 ");
%>
é‹è¡Œä¸€ä¸‹çœ‹çœ‹æ•ˆæžœï¼š
åƒè€ƒæ–‡ç« :
作者: |
fanscial |
標題: |
《 AJAX 簡介》 |
網å€ï¼š |
http://www.blogjava.net/fanscial/archive/2005/08/31/11628.html |
||
作者: |
Amour GUO |
標題: |
《 AJAX 內部交æµæ–‡æª”》 |
網å€ï¼š |
|||
作者: |
MoztwWiki |
標題: |
《 AJAX 上手篇》 |
網å€ï¼š |
http://wiki.moztw.org/index.php/AJAX_%E4%B8%8A%E6%89%8B%E7%AF%87 |
æ›´å¤šæ–‡ç« ã€æŠ€è¡“交æµã€å•†å‹™åˆä½œã€è¯ç³»åšä¸»
微信掃碼或æœç´¢ï¼šz360901061

å¾®ä¿¡æŽƒä¸€æŽƒåŠ æˆ‘ç‚ºå¥½å‹
QQ號è¯ç³»ï¼š 360901061
您的支æŒæ˜¯åšä¸»å¯«ä½œæœ€å¤§çš„動力,如果您喜æ¡æˆ‘çš„æ–‡ç« ï¼Œæ„Ÿè¦ºæˆ‘çš„æ–‡ç« å°æ‚¨æœ‰å¹«åŠ©ï¼Œè«‹ç”¨å¾®ä¿¡æŽƒæ下é¢äºŒç¶ç¢¼æ”¯æŒåšä¸»2å…ƒã€5å…ƒã€10å…ƒã€20å…ƒç‰æ‚¨æƒ³æ的金é¡å§ï¼Œç‹ ç‹ é»žæ“Šä¸‹é¢çµ¦é»žæ”¯æŒå§ï¼Œç«™é•·éžå¸¸æ„Ÿæ¿€æ‚¨ï¼æ‰‹æ©Ÿå¾®ä¿¡é•·æŒ‰ä¸èƒ½æ”¯ä»˜è§£æ±ºè¾¦æ³•ï¼šè«‹å°‡å¾®ä¿¡æ”¯ä»˜äºŒç¶ç¢¼ä¿å˜åˆ°ç›¸å†Šï¼Œåˆ‡æ›åˆ°å¾®ä¿¡ï¼Œç„¶åŽé»žæ“Šå¾®ä¿¡å³ä¸Šè§’掃一掃功能,é¸æ“‡æ”¯ä»˜äºŒç¶ç¢¼å®Œæˆæ”¯ä»˜ã€‚
ã€æœ¬æ–‡å°æ‚¨æœ‰å¹«åŠ©å°±å¥½ã€‘å…ƒ
