首頁 web前端 js教程 原生js如何實作AJAX、JSONP及DOM載入完成事件

原生js如何實作AJAX、JSONP及DOM載入完成事件

Nov 21, 2016 pm 02:47 PM
javascript

一、JS原生Ajax

ajax:一種請求資料的方式,不需要刷新整個頁面;
ajax的技術核心是XMLHttpRequest 物件;
ajax 請求流程:建立XMLHttpRequest 物件、連接資料伺服器、傳送請求、接收回應資料;

下面簡單封裝一個函數,之後稍作解釋

  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及其以上版本中支援原生的XHR 對象,因此可以直接使用: var oAjax = new XMLHttpRequest(); 1.2、IE6及其先前的版本中,XHR物件是透過MSXML庫中的一個ActiveX物件實現的。有的書中細化了IE中此類物件的三種不同版本,即MSXML2.XMLHttp.6.0;個人感覺太麻煩,可以直接使用下面的語句創建: var oAjax =new ActiveXObject('Microsoft.XMLHTTP');

2、連接和發送

2.1、open()函數的三個參數:請求方式、請求地址、是否非同步請求(同步請求的情況極少,至今還沒用過);

2.2、GET 請求方式是透過URL參數將資料提交到伺服器的,POST則是透過將資料作為send 的參數提交到伺服器;

2.3、POST 請求中,在發送資料之前,要設定表單提交的內容類型;

2.4、提交到伺服器的參數必須經過encodeURIComponent() 方法進行編碼,實際上在參數清單」key=value」的形式中,key 和value 都需要編碼,因為會包含特殊字元。每次請求的時候都會在參數清單中拼入一個 “v=xx” 的字串,這樣是為了拒絕緩存,每次都直接請求到伺服器上。

    encodeURI() :用於整個URI 的編碼,不會對本身屬於URI 的特殊字元進行編碼,如冒號、正斜線、問號和井號;其對應的解碼函數decodeURI();

:用於對URI 中的某一部分進行編碼,會對它發現的任何非標準字元進行編碼;其對應的解碼函數decodeURIComponent();


3、接收

3.1、接收到回應後,回應的資料會自動填入XHR對象,相關屬性如下

    responseText:回應回傳的主體內容,為字串型別;

    responseXML:如果回應的內容型別是"text/xml" 或"application/xml",這個屬性中將保存著對應的xml 數據,是XML 對應的document 類型;
    status:回應的HTTP狀態碼;
    statusText:HTTP狀態的說明;

3.2、XHR statusText:HTTP狀態的說明;

3.2、XHR表示物件的readyState屬性表示請求/回應過程的當前活動階段,這個屬性的值如下
  0-未初始化,尚未呼叫open()方法;
  1-啟動,呼叫了open()方法,未呼叫send()方法;
  2-傳送,已經呼叫了send()方法,未接收到回應;
  3-接收,已經接收到部分回應資料;
  4-完成,已經接收到全部回應資料;

只要readyState 的數值變化,就會呼叫readystatechange 事件,(其實為了邏輯上通順,可以把邏輯上通順,可以把邏輯上通順,可以把邏輯上通順,可以把邏輯上通順readystatechange放到send之後,因為send時請求伺服器,會進行網路通信,需要時間,在send之後指定readystatechange事件處理程序也是可以的,我通常都是這樣用,但為了規範和跨瀏覽器相容性,還是在open之前進行指定吧)。

3.3、在readystatechange事件中,先判斷回應是否接收完成,然後判斷伺服器是否成功處理請求,xhr.status 是狀態碼,狀態碼以2開頭的都是成功,304表示從快取中獲取,上面的代碼在每次請求的時候都加入了隨機數,所以不會從快取中取值,故狀態不需判斷。

4、ajax請求是不能跨域的!

二、JSONP

  JSONP(JSON with Padding) 是一種跨域請求方式。主要原理是利用了script 標籤可以跨域請求的特點,由其src 屬性發送請求到伺服器,伺服器返回js 程式碼,網頁端接受回應,然後就直接執行了,這和透過script 標籤引用外部文件的原理是一樣的。

  JSONP由兩部分組成:回呼函數和數據,回呼函數一般是由網頁端控制,作為參數發往伺服器端,伺服器端把該函數和數據拼成字串返回。

  例如網頁端建立一個 script 標籤,並給其 src 賦值為 http://www.superfiresun.com/json/?callback=process, 此時網頁端就發起一個請求。服務端將要傳回的資料拼好最為函數的參數傳入,服務端傳回的資料格式類似”process({'name':'superfiresun'})”,網頁端接收到了回應值,因為請求者是script,所以相當於直接呼叫process 方法,並且傳入了一個參數。

  單看響應回傳的數據,JSONP 比 ajax 方式就多了一個回呼函數。

 function jsonp(options) {
        options = options || {};
        if (!options.url || !options.callback) {
            throw new Error("参数不合法");
        }

        //创建 script 标签并加入到页面中
        var callbackName = (&#39;jsonp_&#39; + Math.random()).replace(".", "");
        var oHead = document.getElementsByTagName(&#39;head&#39;)[0];
        options.data[options.callback] = callbackName;
        var params = formatParams(options.data);
        var oS = document.createElement(&#39;script&#39;);
        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 + &#39;?&#39; + 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) + &#39;=&#39; + encodeURIComponent(data[i]));
        }
        return arr.join(&#39;&&#39;);
    }
登入後複製

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(&#39;DOMContentLoaded&#39;, function () {
                readyFn && readyFn();
            }, false);
        } else {
            //方案1和2  哪个快用哪一个
            var bReady = false;
            //方案1
            document.attachEvent(&#39;onreadystatechange&#39;, function () {
                if (bReady) {
                    return;
                }
                if (document.readyState == &#39;complete&#39; || 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 进程空闲,则会立即执行该代码。


本網站聲明
本文內容由網友自願投稿,版權歸原作者所有。本站不承擔相應的法律責任。如發現涉嫌抄襲或侵權的內容,請聯絡admin@php.cn

熱AI工具

Undresser.AI Undress

Undresser.AI Undress

人工智慧驅動的應用程序,用於創建逼真的裸體照片

AI Clothes Remover

AI Clothes Remover

用於從照片中去除衣服的線上人工智慧工具。

Undress AI Tool

Undress AI Tool

免費脫衣圖片

Clothoff.io

Clothoff.io

AI脫衣器

Video Face Swap

Video Face Swap

使用我們完全免費的人工智慧換臉工具,輕鬆在任何影片中換臉!

熱工具

記事本++7.3.1

記事本++7.3.1

好用且免費的程式碼編輯器

SublimeText3漢化版

SublimeText3漢化版

中文版,非常好用

禪工作室 13.0.1

禪工作室 13.0.1

強大的PHP整合開發環境

Dreamweaver CS6

Dreamweaver CS6

視覺化網頁開發工具

SublimeText3 Mac版

SublimeText3 Mac版

神級程式碼編輯軟體(SublimeText3)

如何使用WebSocket和JavaScript實現線上語音辨識系統 如何使用WebSocket和JavaScript實現線上語音辨識系統 Dec 17, 2023 pm 02:54 PM

如何使用WebSocket和JavaScript實現線上語音辨識系統引言:隨著科技的不斷發展,語音辨識技術已成為了人工智慧領域的重要組成部分。而基於WebSocket和JavaScript實現的線上語音辨識系統,具備了低延遲、即時性和跨平台的特點,成為了廣泛應用的解決方案。本文將介紹如何使用WebSocket和JavaScript來實現線上語音辨識系

WebSocket與JavaScript:實現即時監控系統的關鍵技術 WebSocket與JavaScript:實現即時監控系統的關鍵技術 Dec 17, 2023 pm 05:30 PM

WebSocket與JavaScript:實現即時監控系統的關鍵技術引言:隨著互聯網技術的快速發展,即時監控系統在各個領域中得到了廣泛的應用。而實現即時監控的關鍵技術之一就是WebSocket與JavaScript的結合使用。本文將介紹WebSocket與JavaScript在即時監控系統中的應用,並給出程式碼範例,詳細解釋其實作原理。一、WebSocket技

如何利用JavaScript和WebSocket實現即時線上點餐系統 如何利用JavaScript和WebSocket實現即時線上點餐系統 Dec 17, 2023 pm 12:09 PM

如何利用JavaScript和WebSocket實現即時線上點餐系統介紹:隨著網路的普及和技術的進步,越來越多的餐廳開始提供線上點餐服務。為了實現即時線上點餐系統,我們可以利用JavaScript和WebSocket技術。 WebSocket是一種基於TCP協定的全雙工通訊協議,可實現客戶端與伺服器的即時雙向通訊。在即時線上點餐系統中,當使用者選擇菜餚並下訂單

如何使用WebSocket和JavaScript實現線上預約系統 如何使用WebSocket和JavaScript實現線上預約系統 Dec 17, 2023 am 09:39 AM

如何使用WebSocket和JavaScript實現線上預約系統在當今數位化的時代,越來越多的業務和服務都需要提供線上預約功能。而實現一個高效、即時的線上預約系統是至關重要的。本文將介紹如何使用WebSocket和JavaScript來實作一個線上預約系統,並提供具體的程式碼範例。一、什麼是WebSocketWebSocket是一種在單一TCP連線上進行全雙工

JavaScript與WebSocket:打造高效率的即時天氣預報系統 JavaScript與WebSocket:打造高效率的即時天氣預報系統 Dec 17, 2023 pm 05:13 PM

JavaScript和WebSocket:打造高效的即時天氣預報系統引言:如今,天氣預報的準確性對於日常生活以及決策制定具有重要意義。隨著技術的發展,我們可以透過即時獲取天氣數據來提供更準確可靠的天氣預報。在本文中,我們將學習如何使用JavaScript和WebSocket技術,來建立一個高效的即時天氣預報系統。本文將透過具體的程式碼範例來展示實現的過程。 We

簡易JavaScript教學:取得HTTP狀態碼的方法 簡易JavaScript教學:取得HTTP狀態碼的方法 Jan 05, 2024 pm 06:08 PM

JavaScript教學:如何取得HTTP狀態碼,需要具體程式碼範例前言:在Web開發中,經常會涉及到與伺服器進行資料互動的場景。在與伺服器進行通訊時,我們經常需要取得傳回的HTTP狀態碼來判斷操作是否成功,並根據不同的狀態碼來進行對應的處理。本篇文章將教你如何使用JavaScript來取得HTTP狀態碼,並提供一些實用的程式碼範例。使用XMLHttpRequest

javascript如何使用insertBefore javascript如何使用insertBefore Nov 24, 2023 am 11:56 AM

用法:在JavaScript中,insertBefore()方法用於在DOM樹中插入一個新的節點。這個方法需要兩個參數:要插入的新節點和參考節點(即新節點將要插入的位置的節點)。

JavaScript與WebSocket:打造高效率的即時影像處理系統 JavaScript與WebSocket:打造高效率的即時影像處理系統 Dec 17, 2023 am 08:41 AM

JavaScript是一種廣泛應用於Web開發的程式語言,而WebSocket則是一種用於即時通訊的網路協定。結合二者的強大功能,我們可以打造一個高效率的即時影像處理系統。本文將介紹如何利用JavaScript和WebSocket來實作這個系統,並提供具體的程式碼範例。首先,我們需要明確指出即時影像處理系統的需求和目標。假設我們有一個攝影機設備,可以擷取即時的影像數

See all articles