Ajax原理-原生js的XMLHttpRequest对象意义

Ajax原理-原生js的XMLHttpRequest对象意义

  Ajax是对Asynchronous JavaScript + XML的简写,这一技术能够向服务器请求额外的数据而无需卸载页面,会带来很好的用户体验。Ajax技术的核心是XMLHttpRequest(简称XHR)对象,XHR为向服务器发送请求和解析服务器响应提供了流畅的接口,能够以异步方式从服务器府区区获取更多信息而不必刷新页面。使用XML对象取得新数据然后在通过DOM将新数据插入到页面中。
这里写图片描述
一:XMLHttpRequest对象
  IE5是第一款引入XHR对象的浏览器,XHR对象是通过MSXML库中的一个ActiveX对象实现的。因此,在IE中可能会遇到三种不同版本的XHR对象:MSXML2.XMLHttp、MSXML2.XMLHttp.3.0、MSXML2.XMLHttp.6.0 。例如:

    function createXHR(){
        if(typeof arguments.callee.activeXString != 'string'){
            var versions = ['MSXML2.XMLHttp.6.0','MSXML2.XMLHttp','MSXML2.XMLHttp.3.0'];
            for(var i=0; i<versions.length; i++){
                try{
                    new ActiveXObject(versions[i]);
                    arguments.callee.activeXString = versions[i];
                    break;
                }catch(e){
                    console.log('no');
                }
            }
        }
        return new ActiveXObject(arguments.callee.activeXString);
    }

这个函数会根据IE中可用的MSXML库的情况创建最新版本的XHR对象,IE7Firefox、Opera、Chrome和Safari都支持原生的XHR对象,在这些浏览器中创建XHR对象要这样:var xhr = new XMLHttpRequest();,加入你想支持IE7及更高的版本,那么,大可丢掉前面定义的哪个函数,而只用原生的XHR实现。但是,如果你必须要使用IE更早的版本,可以在这个createXHR()函数中加入原生XHR对象的支持。

        function createXHR() {
            if(XMLHttpRequest) {
                return new XMLHttpRequest();
            } else if(ActiveXObject) {
                if(typeof arguments.callee.activeXString != 'string') {
                    var versions = ['MSXML2.XMLHttp.6.0', 'MSXML2.XMLHttp', 'MSXML2.XMLHttp.3.0'];
                    for(var i = 0; i < versions.length; i++) {
                        try {
                            new ActiveXObject(versions[i]);
                            arguments.callee.activeXString = versions[i];
                            break;
                        } catch(e) {
                            console.log('no');
                        }
                    }
                }
                return new ActiveXObject(arguments.callee.activeXString);
            } else {
                throw new Error("No XHR object available");
            }
        }

二:XHR的用法?
  使用XHR对象时,要调用的第一个方法是open(),例如:

xhr.open('get','somfile.txt',false);
xhr.send(null);

这里send()方法,如果不需要向请求主体发送数据,最好传入null参数,因为这个参数对有些浏览器来说是必须的。
  由于这次响应式同步的,所以,js代码会等到服务器响应之后再继续执行。收到响应后,响应数据会自动填充XHR对象的属性,相关属性如下:
responseText:作为响应主体被返回的文本;
responseXML:作为相应的内容类型是text/xml或application/xml,这个属性中将保存包含着相应数据的XMLDOM文档;
status:相应的http状态;
statusText:http状态的说明。
在接收到响应之后,第一步检查status属性,当xhr.status为200时候,说明接受成功,当xhr.status为304的时候,表示请求的资源没有被修改,可以直接使用浏览器中缓存的版本。代码如下:

                if(xhr.readyState == 4 && (xhr.status == 200 || xhr.status == 304)) {
                    document.getElementById("myDiv").innerHTML = xhr.responseText;
                } else {
                    "Request was unsuccessful: "  + xhr.status;
                }

  异步用法
  大多数情况下我们是要发送异步请求,才能让JavaScript继续执行当前的活动阶段。取值如下:
0:未初始化,尚未调用open()方法。
1.启动。已经调用open()方法,但尚未调用send()方法。
2.发送,已经调用send()方法,为接受到响应。
3.接受。已经接受部分响应数据。
4.完成。全部接受响应的数据,并且可以在客户端使用。
只要readyState属性的值发生改变,都会触发一次onreadyStateChange事件。代码如下:

        function loadXMLDoc() {
            var xhr = createXHR();
            xhr.onreadystatechange = function() {
                console.log(xhr)
                if(xhr.readyState == 4 && (xhr.status == 200 || xhr.status == 304)) {
                    document.getElementById("myDiv").innerHTML = xhr.responseText;
                } else {
                    "Request was unsuccessful: "  + xhr.status;
                }
            }

            xhr.open('GET', 'somfile.txt', true);
            xhr.send(null);
        }

另外,在接收到响应之前,还可以调用abort()方法,取消异步请求:xhr.abort();
三:用setRequestHeader设置自定义请求头
这个方法接受两个参数:头部字段的名称和头部字段的值。服务器在接受到这种自定义的头部信息之后,可以执行后续操作,建议使用,否则可能会影响到服务器的响应。

        function loadXMLDoc(){
            var xhr = createXHR();
            xhr.onreadystatechange = function(){
                if(xhr.readyState==4 || xhr.status==200){
                    document.getElementById("myDiv").innerHTML = xhr.responseText;
                }else{
                    "Request was unsuccessful: "  + xhr.status;
                }
            }
            xhr.open('GET','somfile.txt',true);
            xhr.setRequestHeader('MyHeader','MyValue');
            xhr.send(null);
        }

四:GET请求
  对XHR而言,位于传入open()方法的URL末尾的查询字符串必须经过正确的编码才行。
使用GET请求经常会发生的一个错误,就是查询字符串格式有问题。查询字符串中每个参数的名称和值都必须使用encodeURIComponent()进行编码,然后才能放到URL的末尾,而且所用名-值对都必须由&分割,如下面所示:

<body>
        name:
        <input type="text" name="name">
        <br> book:
        <input type="text" name="book">
        <br>
        <input type="button" id="submit" value="submit" >
</body>
<script type="text/javascript">
    function createXHR() {
        if (XMLHttpRequest) {
            return new XMLHttpRequest();
        } else {
            return new ActiveXObject('Microsoft.XMLHTTP');
        }
    };
    //get方式,键值对加工
    function addURLParam(url, name, value) {
        url += (url.indexOf('?') == -1 ? '?' : '&');
        url += encodeURIComponent(name) + '=' + encodeURIComponent(value);
        return url;
    }
    //模拟表单提交
    function formSubmit() {
        //获取文本框节点
        var names = document.querySelectorAll('input')[0].value;
        var books = document.querySelectorAll('input')[1].value;
        console.log(names)
        var xhr = createXHR();
        xhr.onreadystatechange = function () {
            if (xhr.readyState == 4 || xhr.status == 200) {
                console.log(xhr.responseText)
            }
        }
        var url = '01.php';
        //添加参数
        url = addURLParam(url, 'name', names);
        url = addURLParam(url, 'book', books);
        console.log(url)
        //初始化请求
        xhr.open("get", url, true);
        xhr.send(null);
    }
    var sub = document.getElementById('submit');
    sub.onclick = function(){
        formSubmit();
    }
</script>

五:POST请求
  服务器对post请求不一样的,因此,服务器端必须有程序来读取发送过来的原始数据,并从中解析出有用的部分:首先,将Content-Type头部信息设置为application/x-www-form-urlencoded,也就是表单提交时的内容类型,其次是以适当的格式创建一个字符串,如果需要将POST数据进行序列化以便服务器方便处理,就需要XMLHttpRequest2级定义的FormData类型。即:

var data = new FormData();
data.append('name','bangbang');
... ...
xhr.open('post','02.php',true);
var form = document.getElementById('form1');
xhr.send(new FormData(form));

当然,我们可以用自定义的serialize()函数来处理。
例如:

<body>
    <form id="form1">
        name:
        <input type="text" name="name">
        <br> book:
        <input type="text" name="book">
        <br>
        <input type="button" id="submit" value="submit">
    </form>
    <div id="con"></div>
</body>
<script type="text/javascript">
    //序列化函数
    function serialize(form) {
        var parts = [],
            field = null,
            option,
            optValue;
        for (var i = 0; i < form.elements.length; i++) {
            field = form.elements[i];
            switch (field.type) {
            case "select-one":
            case "select-multiple":
                if (field.name.length) {
                    for (var j = 0; j < field.options.length; j++) {
                        option = field.options[j];
                        if (option.selected) {
                            optValue = '';
                            if (optioin.hasAttribute) {
                                optValue = (option.hasAttribute('value') ? option.value : option.text);
                            } else {
                                optValue = (option.attributes['value'].specified ? option.value : option.text);
                            }
                            parts.push(encodeURIComponent(field.name) + '=' + encodeURIComponent(optValue));
                        }
                    }
                }
                break;
            case undefined: //字段集
            case 'file': //文件输入
            case 'submit': //提交按钮
            case 'reset': //重置按钮
            case 'button': //自定义按钮
                break;
            case 'radio': //单选按钮
            case 'checkbox': //复选框
                if (!field.checked) {
                    break;
                }
            default:
                if (field.name.length) {
                    parts.push(encodeURIComponent(field.name) + '=' + encodeURIComponent(field.value));
                }
            }
        }
        return parts.join('&');
    }

    function createXHR() {
        if (XMLHttpRequest) {
            return new XMLHttpRequest();
        } else {
            return new ActiveXObject('Microsoft.XMLHTTP');
        }
    };

    function formSubmit() {
        var xhr = createXHR();
        console.log(xhr.readyState);
        xhr.onreadystatechange = function () {
                if (xhr.readyState == 4 || xhr.status == 200) {
                    console.log(xhr.responseText);
                    document.getElementById('con').innerHTML = xhr.responseText;
                }
            }
            //初始化请求
        xhr.open("post", '02.php', true);
        xhr.setRequestHeader("Content-type", "application/x-www-form-urlencoded");
        var form = document.getElementById('form1');
        console.log(serialize(form));
        xhr.send(serialize(form));
    }
    var sub = document.getElementById('submit');
    sub.onclick = function () {
        formSubmit();
    }
</script>
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值