Baseline Widely available *
å¨è¯¥æç¨ä¸ï¼æä»¬å°ä½¿ç¨XMLHttpRequest
æ¥åé HTTP 请æ±ä»¥å®ç°ç½ç«åæå¡å¨ä¹é´çæ°æ®äº¤æ¢ãXMLHttpRequest
常è§åæ¦æ¶©çä½¿ç¨æ
åµé½å°å
å«å¨ä¾åä¸ã
åéä¸ä¸ª HTTP 请æ±ï¼éè¦å建ä¸ä¸ª XMLHttpRequest
å¯¹è±¡ï¼æå¼ä¸ä¸ª URLï¼æååé请æ±ã彿æè¿äºäºå¡å®æåï¼è¯¥å¯¹è±¡å°ä¼å
å«ä¸äºè¯¸å¦ååºä¸»ä½æ HTTP status çæç¨ä¿¡æ¯ã
function reqListener() {
console.log(this.responseText);
}
var oReq = new XMLHttpRequest();
oReq.addEventListener("load", reqListener);
oReq.open("GET", "http://www.example.org/example.txt");
oReq.send();
请æ±ç±»å
éè¿ XMLHttpRequest
çæç请æ±å¯ä»¥æä¸¤ç§æ¹å¼æ¥è·åæ°æ®ï¼å¼æ¥æ¨¡å¼æåæ¥æ¨¡å¼ã请æ±çç±»åæ¯ç±è¿ä¸ª XMLHttpRequest
对象ç open() æ¹æ³ç第ä¸ä¸ªåæ°async
çå¼å³å®çãå¦æè¯¥åæ°çå¼ä¸º false
ï¼å该 XMLHttpRequest
请æ±ä»¥åæ¥æ¨¡å¼è¿è¡ï¼å¦å该è¿ç¨å°ä»¥å¼æ¥æ¨¡å¼å®æãè¿ä¸¤ç§ç±»å请æ±ç详ç»è®¨è®ºåæåå¯ä»¥å¨åæ¥å弿¥è¯·æ±é¡µæ¾å°ã
夿³¨ï¼ ç±äºå¯¹ç¨æ·ä½éªçè´é¢å½±åï¼ä» Gecko 30.0 çæ¬å¼å§ï¼å¨ä¸»çº¿ç¨ä¸çåæ¥è¯·æ±å·²ç»è¢«å¼ç¨ã
夿³¨ï¼ XMLHttpRequest
æé 彿°å¹¶ä¸ä»
éäº XML ææ¡£ãå®ä¹æä»¥ä½¿ç¨âXMLâå¼å¤´æ¯å 为å¨å®è¯ç乿¶ï¼åå
ç¨äºå¼æ¥æ°æ®äº¤æ¢çä¸»è¦æ ¼å¼ä¾¿æ¯ XMLã
W3C è§èå®ä¹äº XMLHttpRequest()
对象çå ç§ç±»åçååºå±æ§ãè¿äºå±æ§åè¯å®¢æ·ç«¯å
³äº XMLHttpRequest
è¿åç¶æçéè¦ä¿¡æ¯ãä¸äºå¤çéææ¬è¿åç±»åçç¨ä¾ï¼å¯è½å
å«ä¸é¢ç« èææè¿°çä¸äºæä½ååæã
å¦æä½ ä½¿ç¨ XMLHttpRequest
æ¥è·å¾ä¸ä¸ªè¿ç¨ç XML ææ¡£çå
容ï¼responseXML
屿§å°ä¼æ¯ä¸ä¸ªç± XML ææ¡£è§£æèæ¥ç DOM 对象ï¼è¿å¾é¾è¢«æä½ååæãè¿éæäºç§ä¸»è¦çåæ XML ææ¡£çæ¹å¼ï¼
RegExp
æ«ææ¶åå°æ¢è¡ç¬¦çå½±åï¼ä½ ä¹è®¸æ³è¦å 餿æçæ¢è¡ç¬¦ãç¶èï¼è¿ç§æ¹æ³æ¯"æåææ®µ"ï¼å ä¸ºå¦æ XML 代ç åç轻微ååï¼è¯¥æ¹æ³å°å¯è½å¤±è´¥ã夿³¨ï¼ å¨ W3C XMLHttpRequest è§èä¸å 许 HTML éè¿ XMLHttpRequest.responseXML 屿§è¿è¡è§£æãæ´å¤è¯¦ç»å 容请é 读 HTML in XMLHttpRequest ãæ¬æ¡æ³¨æå·²å¨è±æåæä¸æ´æ°ã
夿³¨ï¼ XMLHttpRequest
ç°å¨å¯ä»¥ä½¿ç¨ responseXML
屿§è§£é HTMLã请é
读 HTML in XMLHttpRequest è¿ç¯æç« äºè§£ç¸å
³ç¨æ³ã
å¦æä½¿ç¨ XMLHttpRequest
ä»è¿ç«¯è·åä¸ä¸ª HTML 页é¢ï¼åææ HTML æ è®°ä¼ä»¥å符串çå½¢å¼åæ¾å¨ responseText 屿§éï¼è¿æ ·å°±ä½¿å¾æä½åè§£æè¿äºæ è®°åå¾å°é¾ãè§£æè¿äº HTML æ è®°ä¸»è¦æä¸ç§æ¹å¼ï¼
XMLHttpRequest.responseXML
屿§ãfragment.body.innerHTML
注å
¥å°ä¸ä¸ª ææ¡£ç段 ä¸ï¼å¹¶éå DOM ä¸ççæ®µã尽管 XMLHttpRequest
ä¸è¬ç¨æ¥åéåæ¥æ¶ææ¬æ°æ®ï¼ä½å
¶å®ä¹å¯ä»¥åé忥æ¶äºè¿å¶å
容ãæè®¸å¤ç»è¿è¯å¥½æµè¯çæ¹æ³æ¥å¼ºå¶ä½¿ç¨ XMLHttpRequest
åéäºè¿å¶æ°æ®ãå©ç¨ XMLHttpRequest
对象ç overrideMimeType()
æ¹æ³æ¯ä¸ä¸ªè§£å³æ¹æ¡ï¼è½ç¶å®å¹¶ä¸æ¯ä¸ä¸ªæ åæ¹æ³ã
var oReq = new XMLHttpRequest();
oReq.open("GET", url);
// 以äºè¿å¶åç¬¦ä¸²å½¢å¼æ£ç´¢æªå¤ççæ°æ®
oReq.overrideMimeType("text/plain; charset=x-user-defined");
/* ... */
ç¶èï¼èªä» responseType
屿§ç®åæ¯æå¤§ééå çå
容类ååï¼å·²ç»åºç°äºå¾å¤çç°ä»£ææ¯ï¼å®ä»¬ä½¿å¾åé忥æ¶äºè¿å¶æ°æ®å徿´å 容æã
ä¾å¦ï¼èè以ä¸ä»£ç ï¼å®ä½¿ç¨ "arraybuffer"
ç responseType
æ¥å°è¿ç¨å
容è·åå°ä¸ä¸ªåå¨åçäºè¿å¶æ°æ®ç ArrayBuffer
对象ä¸ã
var oReq = new XMLHttpRequest();
oReq.onload = function (e) {
var arraybuffer = oReq.response; // 䏿¯ responseTextï¼
/* ... */
};
oReq.open("GET", url);
oReq.responseType = "arraybuffer";
oReq.send();
æ´å¤ç¤ºä¾è¯·åè åé忥æ¶äºè¿å¶æ°æ®ã
çæµè¿åº¦XMLHttpRequest
æä¾äºåç§å¨è¯·æ±è¢«å¤çæé´åççäºä»¶ä»¥ä¾çå¬ãè¿å
æ¬å®æè¿åº¦éç¥ãé误éç¥ï¼ççã
æ¯æ DOM ç progress äºä»¶çæµä¹äº XMLHttpRequest
ä¼ è¾ï¼éµå¾ª Web API è¿åº¦äºä»¶è§èï¼è¿äºäºä»¶å®ç°äº ProgressEvent
æ¥å£ã
progress
æ£ç´¢çæ°æ®éåçäºååã
load
ä¼ è¾å®æï¼æææ°æ®ä¿åå¨ response
ä¸ã
var oReq = new XMLHttpRequest();
oReq.addEventListener("progress", updateProgress);
oReq.addEventListener("load", transferComplete);
oReq.addEventListener("error", transferFailed);
oReq.addEventListener("abort", transferCanceled);
oReq.open();
// ...
// æå¡ç«¯å°å®¢æ·ç«¯çä¼ è¾è¿ç¨ï¼ä¸è½½ï¼
function updateProgress(oEvent) {
if (oEvent.lengthComputable) {
var percentComplete = (oEvent.loaded / oEvent.total) * 100;
// ...
} else {
// æ»å¤§å°æªç¥æ¶ä¸è½è®¡ç®è¿ç¨ä¿¡æ¯
}
}
function transferComplete(evt) {
console.log("The transfer is complete.");
}
function transferFailed(evt) {
console.log("An error occurred while transferring the file.");
}
function transferCanceled(evt) {
console.log("The transfer has been canceled by the user.");
}
第 3-6 è¡ä¸ºå¤ç§äºä»¶æ·»å äºäºä»¶çå¬ï¼è¿äºäºä»¶å¨ä½¿ç¨ XMLHttpRequest
æ§è¡æ°æ®ä¼ è¾æ¶è¢«ååºã
夿³¨ï¼ ä½ éè¦å¨è¯·æ±è°ç¨ open()
ä¹åæ·»å äºä»¶çå¬ãå¦å progress
äºä»¶å°ä¸ä¼è¢«è§¦åã
å¨ä¸ä¸ä¸ªä¾åä¸ï¼progress äºä»¶è¢«æå®ç± updateProgress()
彿°å¤çï¼å¹¶æ¥æ¶å°ä¼ è¾çæ»åèæ°åå·²ç»ä¼ è¾çåèæ°ï¼å®ä»¬åå«å¨äºä»¶å¯¹è±¡ç total
å loaded
屿§éã使¯å¦æ lengthComputable
屿§ç弿¯ falseï¼é£ä¹æå³çæ»åèæ°æ¯æªç¥å¹¶ä¸ total çå¼ä¸ºé¶ã
progress äºä»¶åæ¶åå¨äºä¸è½½åä¸ä¼ çä¼ è¾ãä¸è½½ç¸å
³äºä»¶å¨ XMLHttpRequest
对象ä¸è¢«è§¦åï¼å°±åä¸é¢çä¾å䏿 ·ãä¸ä¼ ç¸å
³äºä»¶å¨ XMLHttpRequest.upload
对象ä¸è¢«è§¦åï¼åä¸é¢è¿æ ·ï¼
var oReq = new XMLHttpRequest();
oReq.upload.addEventListener("progress", updateProgress);
oReq.upload.addEventListener("load", transferComplete);
oReq.upload.addEventListener("error", transferFailed);
oReq.upload.addEventListener("abort", transferCanceled);
oReq.open();
夿³¨ï¼ progress äºä»¶å¨ä½¿ç¨ file:
åè®®çæ
åµä¸æ¯æ æçã
夿³¨ï¼ ä» Gecko 9.0 å¼å§ï¼è¿åº¦äºä»¶ç°å¨å¯ä»¥ä¾æäºæ¯ä¸ä¸ªä¼ å ¥çæ°æ®åï¼å æ¬è¿åº¦äºä»¶è¢«è§¦ååå¨å·²ç»æ¥åäºæåä¸ä¸ªæ°æ®å ä¸è¿æ¥å·²ç»è¢«å ³éçæ åµä¸æ¥æ¶å°çæåä¸ä¸ªåãè¿ç§æ åµä¸ï¼å½è¯¥æ°æ®å ç load äºä»¶åçæ¶ progress äºä»¶ä¼è¢«èªå¨è§¦åãè¿ä½¿ä½ å¯ä»¥åªå ³æ³¨ progress äºä»¶å°±å¯ä»¥å¯é ççæµè¿åº¦ã
夿³¨ï¼ å¨ Gecko 12.0 ä¸ï¼å½ responseType
为 "moz-blob" æ¶ï¼å¦æä½ ç progress äºä»¶è¢«è§¦åï¼åååºç弿¯ä¸ä¸ªå
å«äºæ¥æ¶å°çæ°æ®ç Blob
ã
ä½¿ç¨ loadend
äºä»¶å¯ä»¥ä¾¦æµå°ææçä¸ç§å è½½ç»ææ¡ä»¶ï¼abort
ãload
ï¼æ error
ï¼ï¼
req.addEventListener("loadend", loadEnd);
function loadEnd(e) {
console.log(
"The transfer finished (although we don't know if it succeeded or not).",
);
}
éè¦æ³¨æçæ¯ï¼æ²¡ææ¹æ³å¯ä»¥ç¡®åçç¥é loadend
äºä»¶æ¥æ¶å°çä¿¡æ¯æ¯æ¥èªä½ç§æ¡ä»¶å¼èµ·çæä½ç»æ¢ï¼ä½æ¯ä½ å¯ä»¥å¨ææä¼ è¾ç»æçæ¶å使ç¨è¿ä¸ªäºä»¶å¤çã
XMLHttpRequest
çå®ä¾æä¸¤ç§æ¹å¼æäº¤è¡¨åï¼
FormData
API第äºç§æ¹å¼ï¼ä½¿ç¨ FormData
APIï¼æ¯æç®åæå¿«æ·çï¼ä½æ¯ç¼ºç¹æ¯è¢«æ¶éçæ°æ®æ æ³ä½¿ç¨ JSON.stringify() 转æ¢ä¸ºä¸ä¸ª JSON å符串ã åªä½¿ç¨ AJAX åæ´ä¸ºå¤æï¼ä½ä¹æ´çµæ´»ãæ´å¼ºå¤§ã
å¨å¤§å¤æ°ç¨ä¾ä¸ï¼æäº¤è¡¨åæ¶å³ä¾¿ä¸ä½¿ç¨ FormData
API ä¹ä¸ä¼è¦æ±å
¶ä»ç APIãå¯ä¸çä¾å¤æ
嵿¯ï¼å¦æä½ è¦ä¸ä¼ ä¸ä¸ªæå¤ä¸ªæä»¶ï¼ä½ éè¦é¢å¤ç FileReader
APIã
ä¸ä¸ª html <form>
å¯ä»¥ç¨ä»¥ä¸åç§æ¹å¼åéï¼
POST
æ¹æ³ï¼å¹¶å° enctype
屿§è®¾ç½®ä¸º application/x-www-form-urlencoded
(é»è®¤)POST
æ¹æ³ï¼å¹¶å° enctype
屿§è®¾ç½®ä¸º text/plain
POST
æ¹æ³ï¼å¹¶å° enctype
屿§è®¾ç½®ä¸º multipart/form-data
GET
æ¹æ³ï¼è¿ç§æ
åµä¸ enctype
屿§ä¼è¢«å¿½ç¥ï¼ç°å¨ï¼æä»¬æäº¤ä¸ä¸ªè¡¨åï¼å®éé¢æä¸¤ä¸ªåæ®µï¼åå«è¢«å½å为 foo
å baz
ãå¦æä½ ç¨ POST
æ¹æ³ï¼é£ä¹æå¡å¨å°ä¼æ¥æ¶å°ä¸ä¸ªå符串类似äºä¸é¢ä¸ç§æ
åµä¹ä¸ï¼å
¶ä¸çåºå«ä¾èµäºä½ éç¨ä½ç§ç¼ç ç±»åï¼
POST
ï¼ç¼ç ç±»åï¼application/x-www-form-urlencoded
ï¼é»è®¤ï¼:Content-Type: application/x-www-form-urlencoded foo=bar&baz=The+first+line.%0D%0AThe+second+line.%0D%0A
æ¹æ³ï¼POST
ï¼ç¼ç ç±»åï¼text/plain
ï¼
Content-Type: text/plain foo=bar baz=The first line. The second line.
æ¹æ³ï¼POST
ï¼ç¼ç ç±»åï¼multipart/form-data
ï¼
Content-Type: multipart/form-data; boundary=---------------------------314911788813839 -----------------------------314911788813839 Content-Disposition: form-data; name="foo" bar -----------------------------314911788813839 Content-Disposition: form-data; name="baz" The first line. The second line. -----------------------------314911788813839--
ç¸åçï¼å¦æä½ ç¨ GET
æ¹æ³ï¼åä¸é¢è¿æ ·çå符串å°è¢«ç®åçéå å° URLï¼
?foo=bar&baz=The%20first%20line.%0AThe%20second%20line.ä¸ä¸ªå°æ¡æ¶
ææè¿äºäºæ
齿¯ç±æµè§å¨å¨ä½ æäº¤ä¸ä¸ª <form>
çæ¶åèªå¨å®æçã使¯å¦æä½ æ³è¦ç¨ JavaScript ååæ ·çäºæ
ï¼ä½ ä¸å¾ä¸åè¯è§£é卿æçäºãé£ä¹ï¼å¦ä½åé表åè¿ä»¶äºå¨ä½¿ç¨çº¯ç²¹ç AJAX æ¶ä¼å¤æå°æ æ³å¨è¿éè§£éæ¸
æ¥ãåºäºè¿ä¸ªåå ï¼æä»¬æä¾ä¸ä¸ªå®æ´çï¼ä½ä»ç¶ææ¡çï¼æ¡æ¶ï¼å®å¯ä»¥ä½¿ç¨ææçåç§æäº¤æ¹å¼ï¼çè³ä¸ä¼ æä»¶ï¼
<!doctype html>
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8" />
<title>Sending forms with pure AJAX – MDN</title>
<script type="text/javascript">
"use strict";
/*\
|*|
|*| :: XMLHttpRequest.prototype.sendAsBinary() Polyfill ::
|*|
|*| https://developer.mozilla.org/zh-CN/docs/DOM/XMLHttpRequest#sendAsBinary()
\*/
if (!XMLHttpRequest.prototype.sendAsBinary) {
XMLHttpRequest.prototype.sendAsBinary = function (sData) {
var nBytes = sData.length,
ui8Data = new Uint8Array(nBytes);
for (var nIdx = 0; nIdx < nBytes; nIdx++) {
ui8Data[nIdx] = sData.charCodeAt(nIdx) & 0xff;
}
/* send as ArrayBufferView...: */
this.send(ui8Data);
/* ...or as ArrayBuffer (legacy)...: this.send(ui8Data.buffer); */
};
}
/*\
|*|
|*| :: AJAX Form Submit Framework ::
|*|
|*| https://developer.mozilla.org/zh-CN/docs/DOM/XMLHttpRequest_API/Using_XMLHttpRequest
|*|
|*| This framework is released under the GNU Public License, version 3 or later.
|*| https://www.gnu.org/licenses/gpl-3.0-standalone.html
|*|
|*| Syntax:
|*|
|*| AJAXSubmit(HTMLFormElement);
\*/
var AJAXSubmit = (function () {
function ajaxSuccess() {
/* console.log("AJAXSubmit - Success!"); */
console.log(this.responseText);
/* you can get the serialized data through the "submittedData" custom property: */
/* console.log(JSON.stringify(this.submittedData)); */
}
function submitData(oData) {
/* the AJAX request... */
var oAjaxReq = new XMLHttpRequest();
oAjaxReq.submittedData = oData;
oAjaxReq.onload = ajaxSuccess;
if (oData.technique === 0) {
/* method is GET */
oAjaxReq.open(
"get",
oData.receiver.replace(
/(?:\?.*)?$/,
oData.segments.length > 0 ? "?" + oData.segments.join("&") : "",
),
true,
);
oAjaxReq.send(null);
} else {
/* method is POST */
oAjaxReq.open("post", oData.receiver, true);
if (oData.technique === 3) {
/* enctype is multipart/form-data */
var sBoundary =
"---------------------------" + Date.now().toString(16);
oAjaxReq.setRequestHeader(
"Content-Type",
"multipart\/form-data; boundary=" + sBoundary,
);
oAjaxReq.sendAsBinary(
"--" +
sBoundary +
"\r\n" +
oData.segments.join("--" + sBoundary + "\r\n") +
"--" +
sBoundary +
"--\r\n",
);
} else {
/* enctype is application/x-www-form-urlencoded or text/plain */
oAjaxReq.setRequestHeader("Content-Type", oData.contentType);
oAjaxReq.send(
oData.segments.join(oData.technique === 2 ? "\r\n" : "&"),
);
}
}
}
function processStatus(oData) {
if (oData.status > 0) {
return;
}
/* the form is now totally serialized! do something before sending it to the server... */
/* doSomething(oData); */
/* console.log("AJAXSubmit - The form is now serialized. Submitting..."); */
submitData(oData);
}
function pushSegment(oFREvt) {
this.owner.segments[this.segmentIdx] += oFREvt.target.result + "\r\n";
this.owner.status--;
processStatus(this.owner);
}
function plainEscape(sText) {
/* How should I treat a text/plain form encoding?
What characters are not allowed? this is what I suppose...: */
/* "4\3\7 - Einstein said E=mc2" ----> "4\\3\\7\ -\ Einstein\ said\ E\=mc2" */
return sText.replace(/[\s\=\\]/g, "\\$&");
}
function SubmitRequest(oTarget) {
var nFile,
sFieldType,
oField,
oSegmReq,
oFile,
bIsPost = oTarget.method.toLowerCase() === "post";
/* console.log("AJAXSubmit - Serializing form..."); */
this.contentType =
bIsPost && oTarget.enctype
? oTarget.enctype
: "application\/x-www-form-urlencoded";
this.technique = bIsPost
? this.contentType === "multipart\/form-data"
? 3
: this.contentType === "text\/plain"
? 2
: 1
: 0;
this.receiver = oTarget.action;
this.status = 0;
this.segments = [];
var fFilter = this.technique === 2 ? plainEscape : escape;
for (var nItem = 0; nItem < oTarget.elements.length; nItem++) {
oField = oTarget.elements[nItem];
if (!oField.hasAttribute("name")) {
continue;
}
sFieldType =
oField.nodeName.toUpperCase() === "INPUT"
? oField.getAttribute("type").toUpperCase()
: "TEXT";
if (sFieldType === "FILE" && oField.files.length > 0) {
if (this.technique === 3) {
/* enctype is multipart/form-data */
for (nFile = 0; nFile < oField.files.length; nFile++) {
oFile = oField.files[nFile];
oSegmReq = new FileReader();
/* (custom properties:) */
oSegmReq.segmentIdx = this.segments.length;
oSegmReq.owner = this;
/* (end of custom properties) */
oSegmReq.onload = pushSegment;
this.segments.push(
'Content-Disposition: form-data; name="' +
oField.name +
'"; filename="' +
oFile.name +
'"\r\nContent-Type: ' +
oFile.type +
"\r\n\r\n",
);
this.status++;
oSegmReq.readAsBinaryString(oFile);
}
} else {
/* enctype is application/x-www-form-urlencoded or text/plain or
method is GET: files will not be sent! */
for (
nFile = 0;
nFile < oField.files.length;
this.segments.push(
fFilter(oField.name) +
"=" +
fFilter(oField.files[nFile++].name),
)
);
}
} else if (
(sFieldType !== "RADIO" && sFieldType !== "CHECKBOX") ||
oField.checked
) {
/* NOTE: this will submit _all_ submit buttons. Detecting the correct one is non-trivial. */
/* field type is not FILE or is FILE but is empty */
this.segments.push(
this.technique === 3 /* enctype is multipart/form-data */
? 'Content-Disposition: form-data; name="' +
oField.name +
'"\r\n\r\n' +
oField.value +
"\r\n"
: /* enctype is application/x-www-form-urlencoded or text/plain or method is GET */
fFilter(oField.name) + "=" + fFilter(oField.value),
);
}
}
processStatus(this);
}
return function (oFormElement) {
if (!oFormElement.action) {
return;
}
new SubmitRequest(oFormElement);
};
})();
</script>
</head>
<body>
<h1>Sending forms with pure AJAX</h1>
<h2>Using the GET method</h2>
<form
action="register.php"
method="get"
onsubmit="AJAXSubmit(this); return false;">
<fieldset>
<legend>Registration example</legend>
<p>
First name: <input type="text" name="firstname" /><br />
Last name: <input type="text" name="lastname" />
</p>
<p>
<input type="submit" value="Submit" />
</p>
</fieldset>
</form>
<h2>Using the POST method</h2>
<h3>Enctype: application/x-www-form-urlencoded (default)</h3>
<form
action="register.php"
method="post"
onsubmit="AJAXSubmit(this); return false;">
<fieldset>
<legend>Registration example</legend>
<p>
First name: <input type="text" name="firstname" /><br />
Last name: <input type="text" name="lastname" />
</p>
<p>
<input type="submit" value="Submit" />
</p>
</fieldset>
</form>
<h3>Enctype: text/plain</h3>
<form
action="register.php"
method="post"
enctype="text/plain"
onsubmit="AJAXSubmit(this); return false;">
<fieldset>
<legend>Registration example</legend>
<p>Your name: <input type="text" name="user" /></p>
<p>
Your message:<br />
<textarea name="message" cols="40" rows="8"></textarea>
</p>
<p>
<input type="submit" value="Submit" />
</p>
</fieldset>
</form>
<h3>Enctype: multipart/form-data</h3>
<form
action="register.php"
method="post"
enctype="multipart/form-data"
onsubmit="AJAXSubmit(this); return false;">
<fieldset>
<legend>Upload example</legend>
<p>
First name: <input type="text" name="firstname" /><br />
Last name: <input type="text" name="lastname" /><br />
Sex:
<input id="sex_male" type="radio" name="sex" value="male" />
<label for="sex_male">Male</label>
<input id="sex_female" type="radio" name="sex" value="female" />
<label for="sex_female">Female</label><br />
Password: <input type="password" name="secret" /><br />
What do you prefer:
<select name="image_type">
<option>Books</option>
<option>Cinema</option>
<option>TV</option>
</select>
</p>
<p>
Post your photos:
<input type="file" multiple name="photos[]" />
</p>
<p>
<input
id="vehicle_bike"
type="checkbox"
name="vehicle[]"
value="Bike" />
<label for="vehicle_bike">I have a bike</label><br />
<input
id="vehicle_car"
type="checkbox"
name="vehicle[]"
value="Car" />
<label for="vehicle_car">I have a car</label>
</p>
<p>
Describe yourself:<br />
<textarea name="description" cols="50" rows="8"></textarea>
</p>
<p>
<input type="submit" value="Submit" />
</p>
</fieldset>
</form>
</body>
</html>
è¦æµè¯å®çè¯ï¼å建ä¸ä¸ªå为 register.php
ç页é¢ï¼ä½ä¸ºç¤ºä¾è¡¨åç action
屿§ï¼å¹¶ä¸åªè¾å
¥ä»¥ä¸å
容ï¼
<?php
/* register.php */
header("Content-type: text/plain");
/*
NOTE: You should never use `print_r()` in production scripts, or
otherwise output client-submitted data without sanitizing it first.
Failing to sanitize can lead to cross-site scripting vulnerabilities.
*/
echo ":: data received via GET ::\n\n";
print_r($_GET);
echo "\n\n:: Data received via POST ::\n\n";
print_r($_POST);
echo "\n\n:: Data received as \"raw\" (text/plain encoding) ::\n\n";
if (isset($HTTP_RAW_POST_DATA)) { echo $HTTP_RAW_POST_DATA; }
echo "\n\n:: Files received ::\n\n";
print_r($_FILES);
æ¿æ´»è¿äºä»£ç çè¯æ³å¾ç®åï¼
夿³¨ï¼ è¯¥æ¡æ¶ä½¿ç¨ FileReader
API è¿è¡æä»¶çä¸ä¼ ãè¿æ¯ä¸ä¸ªè¾æ°ç API å¹¶ä¸è¿æªå¨ IE9 å以ä¸çæ¬çæµè§å¨ä¸å®ç°ãå æ¤ï¼ä½¿ç¨ AJAX ä¸ä¼ 仿¯ä¸é¡¹å®éªæ§çææ¯ãå¦æä½ ä¸éè¦ä¸ä¼ äºè¿å¶æä»¶ï¼è¯¥æ¡æ¶å¨å¤§å¤æ°æµè§å¨ä¸è¿è¡è¯å¥½ã
夿³¨ï¼ åéäºè¿å¶å
容çæä½³é徿¯éè¿ ArrayBuffers
æ Blobs
ç»å send()
æ¹æ³çè³ FileReader
API ç readAsArrayBuffer()
æ¹æ³ã使¯ï¼èªä»è¯¥èæ¬çç®çåæå¤ç å¯å符串å çåå§æ°æ®ä»¥æ¥ï¼æä»¬ä½¿ç¨ sendAsBinary()
æ¹æ³ç»å FileReader
API ç readAsBinaryString()
æ¹æ³ãåæ ·å°ï¼ä¸è¿°èæ¬ä»
å½ä½ å¤çå°æä»¶æ¶è¡ä¹ææã妿䏿ç®ä¸ä¼ äºè¿å¶å
容ï¼å°±èèä½¿ç¨ FormData
API æ¥æ¿ä»£ã
夿³¨ï¼ éæ åç sendAsBinary
æ¹æ³ä» Gecko 31 å¼å§å°ä¼åºå¼å¹¶ä¸ä¼å¾å¿«è¢«ç§»é¤ãæ åæ¹æ³ send(Blob data)
å°ä¼åè代ä¹ã
FormData
æé 彿°è½ä½¿ä½ ç¼è¯ä¸ä¸ªé®/å¼å¯¹çéåï¼ç¶åä½¿ç¨ XMLHttpRequest
åéåºå»ãå
¶ä¸»è¦ç¨äºåéè¡¨æ ¼æ°æ®ï¼ä½æ¯ä¹è½è¢«åç¬ç¨æ¥ä¼ è¾è¡¨æ ¼ä¸ç¨æ·æå®çæ°æ®ãä¼ è¾çæ°æ®æ ¼å¼ä¸è¡¨æ ¼ä½¿ç¨ submit()
æ¹æ³åéæ°æ®çæ ¼å¼ä¸è´ï¼å¦æè¯¥è¡¨æ ¼çç¼ç ç±»å被设为 "multipart/form-data"ãFormData 对象å¯ä»¥è¢«ç»å XMLHttpRequest
çå¤ç§æ¹æ³å©ç¨ãä¾å¦ï¼æ³äºè§£å¦ä½å©ç¨ FormData ä¸ XMLHttpRequestï¼è¯·è½¬å°ä½¿ç¨ FormData 对象页é¢ã为äºè¯´æçç®çï¼è¿éæä¸ä¸ªæ©æç示ä¾ï¼è¢«è½¬è¯æäºä½¿ç¨ FormData
API çå½¢å¼ã注æä»¥ä¸ä»£ç çæ®µï¼
<!doctype html>
<html>
<head>
<meta http-equiv="Content-Type" charset="UTF-8" />
<title>Sending forms with FormData – MDN</title>
<script>
"use strict";
function ajaxSuccess() {
console.log(this.responseText);
}
function AJAXSubmit(oFormElement) {
if (!oFormElement.action) {
return;
}
var oReq = new XMLHttpRequest();
oReq.onload = ajaxSuccess();
if (oFormElement.method.toLowerCase() === "post") {
oReq.open("post", oFormElement.action);
oReq.send(new FormData(oFormElement));
} else {
var oField,
sFieldType,
nFile,
sSearch = "";
for (var nItem = 0; nItem < oFormElement.elements.length; nItem++) {
oField = oFormElement.elements[nItem];
if (!oField.hasAttribute("name")) {
continue;
}
sFieldType =
oField.nodeName.toUpperCase() === "INPUT"
? oField.getAttribute("type").toUpperCase()
: "TEXT";
if (sFieldType === "FILE") {
for (
nFile = 0;
nFile < oField.files.length;
sSearch +=
"&" +
escape(oField.name) +
"=" +
escape(oField.files[nFile++].name)
);
} else if (
(sFieldType !== "RADIO" && sFieldType !== "CHECKBOX") ||
oField.checked
) {
sSearch += "&" + escape(oField.name) + "=" + escape(oField.value);
}
}
oReq.open(
"get",
oFormElement.action.replace(
/(?:\?.*)?$/,
sSearch.replace(/^&/, "?"),
),
true,
);
oReq.send(null);
}
}
</script>
</head>
<body>
<h1>Sending forms with FormData</h1>
<h2>Using the GET method</h2>
<form
action="register.php"
method="get"
onsubmit="AJAXSubmit(this); return false;">
<fieldset>
<legend>Registration example</legend>
<p>
First name: <input type="text" name="firstname" /><br />
Last name: <input type="text" name="lastname" />
</p>
<p>
<input type="submit" value="Submit" />
</p>
</fieldset>
</form>
<h2>Using the POST method</h2>
<h3>Enctype: application/x-www-form-urlencoded (default)</h3>
<form
action="register.php"
method="post"
onsubmit="AJAXSubmit(this); return false;">
<fieldset>
<legend>Registration example</legend>
<p>
First name: <input type="text" name="firstname" /><br />
Last name: <input type="text" name="lastname" />
</p>
<p>
<input type="submit" value="Submit" />
</p>
</fieldset>
</form>
<h3>Enctype: text/plain</h3>
<p>The text/plain encoding is not supported by the FormData API.</p>
<h3>Enctype: multipart/form-data</h3>
<form
action="register.php"
method="post"
enctype="multipart/form-data"
onsubmit="AJAXSubmit(this); return false;">
<fieldset>
<legend>Upload example</legend>
<p>
First name: <input type="text" name="firstname" /><br />
Last name: <input type="text" name="lastname" /><br />
Sex:
<input id="sex_male" type="radio" name="sex" value="male" />
<label for="sex_male">Male</label>
<input id="sex_female" type="radio" name="sex" value="female" />
<label for="sex_female">Female</label><br />
Password: <input type="password" name="secret" /><br />
What do you prefer:
<select name="image_type">
<option>Books</option>
<option>Cinema</option>
<option>TV</option>
</select>
</p>
<p>
Post your photos:
<input type="file" multiple name="photos[]" />
</p>
<p>
<input
id="vehicle_bike"
type="checkbox"
name="vehicle[]"
value="Bike" />
<label for="vehicle_bike">I have a bike</label><br />
<input
id="vehicle_car"
type="checkbox"
name="vehicle[]"
value="Car" />
<label for="vehicle_car">I have a car</label>
</p>
<p>
Describe yourself:<br />
<textarea name="description" cols="50" rows="8"></textarea>
</p>
<p>
<input type="submit" value="Submit" />
</p>
</fieldset>
</form>
</body>
</html>
夿³¨ï¼ å¦ä¹åæè¿°ï¼FormData
å¯¹è±¡å¹¶ä¸æ¯ å¯å符串å (stringifiable) ç对象ãå¦æä½ æ³è¦å符串åä¸ä¸ªæäº¤æ°æ®ï¼è¯·ä½¿ç¨è¿ä¸ª æ©æç纯 AJAX ä¾å. åæ¶ä¹è¦æ³¨æï¼å°½ç®¡è¿ä¸ªä¾å䏿ä¸äº file
<input>
åæ®µï¼ä½å½ä½ éè¿ FormData
API æäº¤ä¸ä¸ªè¡¨æ ¼æ¶ï¼ä¹æ é¡»ä½¿ç¨ FileReader
API: æä»¶è¢«èªå¨å 载并ä¸ä¼ ã
function getHeaderTime() {
console.log(
this.getResponseHeader("Last-Modified"),
); /* ä¸ä¸ªåæ³ç GMTString æ¥ææ null */
}
var oReq = new XMLHttpRequest();
oReq.open(
"HEAD" /* ä»
éè¦å¤´é¨ä¿¡æ¯ (headers) æ¶è¯·ä½¿ç¨ HEAD! */,
"yourpage.html",
);
oReq.onload = getHeaderTime;
oReq.send();
æåä¿®æ¹æ¥ææ¹ååçæä½
å åå»ºä¸¤ä¸ªå½æ°ï¼
function getHeaderTime() {
var nLastVisit = parseFloat(
window.localStorage.getItem("lm_" + this.filepath),
);
var nLastModif = Date.parse(this.getResponseHeader("Last-Modified"));
if (isNaN(nLastVisit) || nLastModif > nLastVisit) {
window.localStorage.setItem("lm_" + this.filepath, Date.now());
isFinite(nLastVisit) && this.callback(nLastModif, nLastVisit);
}
}
function ifHasChanged(sURL, fCallback) {
var oReq = new XMLHttpRequest();
oReq.open("HEAD" /* ä½¿ç¨ HEAD - æä»¬ä»
éè¦å¤´é¨ä¿¡æ¯ (headers)! */, sURL);
oReq.callback = fCallback;
oReq.filepath = sURL;
oReq.onload = getHeaderTime;
oReq.send();
}
And to test:
/* æµè¯ä¸ä¸è¿ä¸ªæä»¶ï¼"yourpage.html"... */
ifHasChanged("yourpage.html", function (nModif, nVisit) {
console.log(
"The page '" +
this.filepath +
"' has been changed on " +
new Date(nModif).toLocaleString() +
"!",
);
});
å¦æä½ æ³è¦äºè§£å½å页颿¯å¦åçäºæ¹åï¼è¯·é
读è¿ç¯æç« ï¼document.lastModified
ã
ç°ä»£æµè§å¨éè¿å®ç°è·¨æºèµæºå
±äº«ï¼CORSï¼æ åæ¥æ¯æè·¨ç«è¯·æ±ãåªè¦æå¡å¨ç«¯çé
ç½®å
è®¸ä½ ä»ä½ ç Web åºç¨åé请æ±ï¼å°±å¯ä»¥ä½¿ç¨ XMLHttpRequest
ãå¦åï¼ä¼æåºä¸ä¸ª INVALID_ACCESS_ERR
å¼å¸¸
æä¸ä¸ªè·¨æµè§å¨å ¼å®¹çæ¹æ³ï¼å°±æ¯ç» URL æ·»å æ¶é´æ³ã请确ä¿ä½ é æ å°æ·»å äº "?" or "&" ãä¾å¦ï¼å°ï¼
http://example.com/bar.html -> http://example.com/bar.html?12345 http://example.com/bar.html?foobar=baz -> http://example.com/bar.html?foobar=baz&12345
å 为æ¬å°ç¼å齿¯ä»¥ URL ä½ä¸ºç´¢å¼çï¼è¿æ ·å°±å¯ä»¥ä½¿æ¯ä¸ªè¯·æ±é½æ¯å¯ä¸çï¼ä¹å°±å¯ä»¥è¿æ ·æ¥ç»å¼ç¼åã
ä½ ä¹å¯ä»¥ç¨ä¸é¢çæ¹æ³èªå¨æ´æ¹ç¼åï¼
const req = new XMLHttpRequest();
req.open("GET", url + (/\?/.test(url) ? "&" : "?") + new Date().getTime());
req.send(null);
å®å
¨æ§
è¦å¯ç¨è·¨ç«èæ¬ï¼æ¨èçåæ³æ¯å¯¹ XMLHttpRequest çååºä½¿ç¨ Access-Control-Allow-Origin
ç HTTP æ 头ã
å¦æä½ ç XMLHttpRequest æ¶å° status=0
å statusText=null
çè¿åï¼è¿æå³çè¯·æ±æ æ³æ§è¡ãå°±æ¯æªè¢«åéçï¼UNSENT
ï¼ãä¸ä¸ªå¯è½å¯¼è´çåå æ¯å¨ XMLHttpRequest 卿§è¡ open()
æ¶ï¼XMLHttpRequest
çæ¥æºåçäºæ¹åãè¿ç§æ
嵿¯å¯è½åççï¼ä¾å¦ï¼æä»¬å¨ä¸ä¸ªçªå£ç onunload äºä»¶è§¦åæ¶å¨è¿è¡ä¸ä¸ª XMLHttpRequestï¼ä¹åå建ç XMLHttpRequest ä»ç¶å¨é£éï¼æåå½è¿ä¸ªçªå£å¤±å»ç¦ç¹ãå¦ä¸ä¸ªçªå£è·å¾ç¦ç¹æ¶ï¼å®è¿æ¯åéäºè¯·æ±ï¼ä¹å°±æ¯ open()
ï¼ãæææçé¿å
è¿ä¸ªé®é¢çæ¹æ³æ¯å¨å
³éççªå£è§¦å unload
äºä»¶æ¶ä¸ºæ°çªå£ç DOMActivate
äºä»¶è®¾ç½®ä¸ä¸ªçå¬å¨ã
RetroSearch is an open source project built by @garambo | Open a GitHub Issue
Search and Browse the WWW like it's 1997 | Search results from DuckDuckGo
HTML:
3.2
| Encoding:
UTF-8
| Version:
0.7.4