Heim > Artikel > Web-Frontend > So implementieren Sie AJAX-, JSONP- und DOM-Ladeabschlussereignisse in nativem JS
1. JS natives Ajax
Ajax: eine Möglichkeit, Daten anzufordern, ohne die gesamte Seite zu aktualisieren;
Ajax-Anfrageprozess: XMLHttpRequest-Objekt erstellen , Verbindung zum Server herstellen, Anfragen senden und Antwortdaten empfangen;
ajax({ url: "./TestXHR.aspx", //请求地址 type: "POST", //请求方式 data: { name: "super", age: 20 }, //请求参数 dataType: "json", success: function (response, xml) { // 此处放成功后执行的代码 }, fail: function (status) { // 此处放失败后执行的代码 } }); function ajax(options) { options = options || {}; options.type = (options.type || "GET").toUpperCase(); options.dataType = options.dataType || "json"; var params = formatParams(options.data); //创建 - 非IE6 - 第一步 if (window.XMLHttpRequest) { var xhr = new XMLHttpRequest(); } else { //IE6及其以下版本浏览器 var xhr = new ActiveXObject('Microsoft.XMLHTTP'); } //接收 - 第三步 xhr.onreadystatechange = function () { if (xhr.readyState == 4) { var status = xhr.status; if (status >= 200 && status < 300) { options.success && options.success(xhr.responseText, xhr.responseXML); } else { options.fail && options.fail(status); } } } //连接 和 发送 - 第二步 if (options.type == "GET") { xhr.open("GET", options.url + "?" + params, true); xhr.send(null); } else if (options.type == "POST") { xhr.open("POST", options.url, true); //设置表单提交时的内容类型 xhr.setRequestHeader("Content-Type", "application/x-www-form-urlencoded"); xhr.send(params); } } //格式化参数 function formatParams(data) { var arr = []; for (var name in data) { arr.push(encodeURIComponent(name) + "=" + encodeURIComponent(data[name])); } arr.push(("v=" + Math.random()).replace(".")); return arr.join("&"); }1 1.1, IE7 und seine Die oben genannten Versionen unterstützen native XHR-Objekte, sodass sie direkt verwendet werden können: var oAjax = new XMLHttpRequest();In 1.2, IE6 und früheren Versionen wird das XHR-Objekt über ein ActiveX implementiert Objekt in der MSXML-Bibliothek von. Einige Bücher beschreiben drei verschiedene Versionen solcher Objekte im IE, nämlich MSXML2. =new ActiveXObject('Microsoft.XMLHTTP');Drei Parameter des Öffnens () Funktion: Anforderungsmethode, Anforderungsadresse, ob asynchron angefordert werden soll (synchrone Anforderungen sind selten und wurden bisher nicht verwendet); 2.2 Die GET-Anforderungsmethode sendet Daten über URL-Parameter an den Server POST übermittelt Daten als Sendeparameter an den Server. 2.3 In der POST-Anfrage muss der Inhaltstyp der Formularübermittlung festgelegt werden Der Server muss mit der Methode encodeURIComponent() codiert werden. In der Parameterliste „key=value“ müssen sowohl der Schlüssel als auch der Wert codiert werden, da sie Sonderzeichen enthalten. Bei jeder Anfrage wird die Zeichenfolge „v=xx“ in die Parameterliste geschrieben. Dies dient dazu, das Caching abzulehnen und die Anfrage jedes Mal direkt an den Server zu richten. encodeURI(): wird zum Codieren des gesamten URI verwendet und codiert keine Sonderzeichen, die zum URI gehören, wie Doppelpunkte, Schrägstriche, Fragezeichen und Nummernzeichen; die entsprechende Dekodierungsfunktion decodeURI(); ;
encodeURIComponent(): wird zum Codieren eines bestimmten Teils des URI verwendet und codiert alle nicht standardmäßigen Zeichen, die es findet;
3 🎜>3.1. Nach Erhalt der Antwort werden die Antwortdaten automatisch in „text/xml“ oder „application/xml“ eingefügt. In diesem Attribut werden die entsprechenden XML-Daten gespeichert, bei denen es sich um den Dokumenttyp handelt, der XML entspricht status: der Antwort-HTTP-Statuscode;
statusText: Beschreibung des HTTP-Status ;3.2. Das readyState-Attribut des XHR-Objekts gibt die aktuelle aktive Phase des Anfrage-/Antwortprozesses an Attribut ist wie folgt: 0-Nicht initialisiert, die open()-Methode wurde nicht aufgerufen
1-Start, die open()-Methode wurde aufgerufen, aber die send()-Methode wurde nicht aufgerufen; 🎜> 2-Send, die send()-Methode wurde aufgerufen, aber es wurde keine Antwort empfangen;
4-Complete, alle Antwortdaten wurden empfangen empfangen;
Solange sich der Wert von readyState ändert, wird das Ereignis „readystatechange“ aufgerufen (aus Gründen der logischen Glätte kann „readystatechange“ nach dem Senden platziert werden, da die Anforderung während des Sendens erfolgt Führen Sie die Netzwerkkommunikation durch, was einige Zeit in Anspruch nimmt. Es ist auch möglich, den Readystatechange-Ereignishandler nach dem Senden anzugeben. Normalerweise verwende ich ihn auf diese Weise, aber aus Gründen der Standardisierung und der browserübergreifenden Kompatibilität ist es besser, ihn vor dem Öffnen anzugeben.
3.3. Stellen Sie zunächst fest, ob die Antwort empfangen wurde, und ermitteln Sie dann, ob der Statuscode, der mit 2 beginnt, erfolgreich ist Aus dem Cache fügt der obige Code jeder Anfrage eine Zufallszahl hinzu, sodass der Wert nicht aus dem Cache abgerufen wird und dieser Status nicht beurteilt werden muss.
4. Ajax-Anfragen können nicht domänenübergreifend sein!
2. JSONP
JSONP (JSON mit Padding) ist eine domänenübergreifende Anforderungsmethode. Das Hauptprinzip besteht darin, die Tatsache zu nutzen, dass das Skript-Tag domänenübergreifende Anforderungen stellen kann. Die Anforderung wird über das src-Attribut an den Server gesendet. Der Server gibt den JS-Code zurück und führt ihn dann aus Dies entspricht dem Prinzip der Referenzierung externer Dateien über das Skript-Tag.
JSONP besteht aus zwei Teilen: Rückruffunktion und Daten. Die Rückruffunktion wird im Allgemeinen von der Webseite gesteuert und als Parameter an den Server gesendet. Der Server kombiniert die Funktion und die Daten in einer Zeichenfolge und gibt sie zurück.
function jsonp(options) { options = options || {}; if (!options.url || !options.callback) { throw new Error("参数不合法"); } //创建 script 标签并加入到页面中 var callbackName = ('jsonp_' + Math.random()).replace(".", ""); var oHead = document.getElementsByTagName('head')[0]; options.data[options.callback] = callbackName; var params = formatParams(options.data); var oS = document.createElement('script'); oHead.appendChild(oS); //创建jsonp回调函数 window[callbackName] = function (json) { oHead.removeChild(oS); clearTimeout(oS.timer); window[callbackName] = null; options.success && options.success(json); }; //发送请求 oS.src = options.url + '?' + params; //超时处理 if (options.time) { oS.timer = setTimeout(function () { window[callbackName] = null; oHead.removeChild(oS); options.fail && options.fail({ message: "超时" }); }, time); } }; //格式化参数 function formatParams(data) { var arr = []; for (var name in data) { arr.push(encodeURIComponent(name) + '=' + encodeURIComponent(data[i])); } return arr.join('&'); }
1、因为 script 标签的 src 属性只在第一次设置的时候起作用,导致 script 标签没法重用,所以每次完成操作之后要移除;
2、JSONP这种请求方式中,参数依旧需要编码;
3、如果不设置超时,就无法得知此次请求是成功还是失败;
三、模仿JQuery中的ready()事件
1、DOMContentLoaded事件,在DOM树加载完成之后立即执行,始终会在load之前执行。
IE9+、FF、Chrome、Safari3.1+和Opera9+都支持该事件。
对于不支持该事件的浏览器,可以使用如下代码:
setTimeout(function(){
// 代码块}, 0) ;
DOMContentLoaded 事件只能通过 DOM2 级方式添加,即采用addEventListener()/attachEvent() 方式添加才能够使用。事件对象不会提供任何额外信息。
2、readystatechange事件
IE为DOM文档中的某些部分(区别于 XHR 对象的 readystatechange 事件)提供了该事件,这个事件的目的是提供与文档或元素的加载状态有关的信息,但这个事件的行为有时候也很难预料。支持该事件的对象都有一个readyState属性,注意,不是 event 事件对象。IE、Firefox4+和Opera 支持该事件。
readyState属性的值如下:
“uninitialized” - 未初始化:对象存在但尚未初始化;
“loading” - 正在加载:对象正在加载数据;
“loaded” - 加载完毕,对象加载数据完毕;
“interactive” - 交互:可以操作对象了,但还没有完全加载;
“complete” - 完成:对象已经加载完成;
2.1、并非所有的对象都会经历readyState的这几个阶段,如果这个阶段不适用某个对象,则该对象完全可能跳过该阶段,并没有规定哪个阶段适用于哪个对象。这意味着 readystatechange 事件经常会少于4次,相对应的 readyState 属性值也不是连续的。
2.2、对于 document 而言,interactive 和 complete 阶段会在于 DOMContentLoaded 大致相同的时刻触发 readystatechange 事件;
load 事件和 readystatechange 事件的触发顺序会因页面的外部资源的多少而变化,也就是说,readystatechange 事件并不会一直在 load 事件之前执行。外部资源越多,对 readystatechange 事件就越有利。
interactive 和 complete 的顺序也是不一致的,谁都有可能先执行,引用的外部资源越多,对交互阶段越有利。所以为了尽可能早的执行代码,两个状态要同时判断。
3、doScroll
IE5.5+支持,当页面中有滚动条时,可以用 doScroll("right")/doScroll("down") 等来移动滚动条,这个方法只有等DOM加载完成以后才能用,所以在IE低版本浏览器中可以通过这个属性判断 DOM 结构是否加载完成。介绍这个属性主要是模仿 jquery 中的解决方案。
function ready(readyFn) { //非IE浏览器 if (document.addEventListener) { document.addEventListener('DOMContentLoaded', function () { readyFn && readyFn(); }, false); } else { //方案1和2 哪个快用哪一个 var bReady = false; //方案1 document.attachEvent('onreadystatechange', function () { if (bReady) { return; } if (document.readyState == 'complete' || document.readyState == "interactive") { bReady = true; readyFn && readyFn(); }; }); //方案2 //jquery也会担心doScroll会在iframe内失效,此处是判断当前页是否被放在了iframe里 if (!window.frameElement) { setTimeout(checkDoScroll, 1); } function checkDoScroll() { try { document.documentElement.doScroll("left"); if (bReady) { return; } bReady = true; readyFn && readyFn(); } catch (e) { // 不断检查 doScroll 是否可用 - DOM结构是否加载完成 setTimeout(checkDoScroll, 1); } }; } };
注:
setTimeout(checkDoScroll, 1); 目的是让浏览器尽快执行 checkDoScroll 函数,间隔时间设置为 1ms,对当下的浏览器来说是不太可能的。每个浏览器都有自己默认的最小间隔时间,即使时间设置为最小间隔时间,也只是代表隔这些时间过去之后,JavaScript 会把 checkDoScroll 加入到执行队列中,如果此时 JavaScript 进程空闲,则会立即执行该代码。