Ajax的学习

概述

Web程序最初的目的就是将信息(数据)放到公共的服务器,让所有网络用户都可以通过浏览器访问。

在此之前,我们可以通过以下几种方式让浏览器发出对服务端的请求,获得服务端的数据:

  • 地址栏输入地址,回车,刷新
  • 特定元素的 href 或 src 属性
  • 表单提交

这些方案都是我们无法通过或者很难通过代码的方式进行编程(对服务端发出请求并且接受服务端返回的响应),如果我们可以通过JavaScript直接发送网络请求,那么Web的可能就会更多,随之能够实现的功能也会更多,至少不再是”单机游戏”。

AJAX( Asynchronous JavaScript and XML ) ,(先前是服务器返回XML,现在返回的是JSON格式,所以实际上该技术是AJAJ) 最早出现在2005年的Google Suggest (就是搜索框下的建议列表),是在浏览器端进行网络编程(发送请求、接收响应)的技术方案,它使我们可以通过JavaScript直接获取服务端最新的内容而不必重新加载页面。让Web更能接近桌面应用的用户体验。

AJAX 是一种在无需重新加载整个网页的情况下,能够更新部分网页的技术。

AJAX就是浏览器提供的一套API ,可以通过JavaScript调用,从而实现通过代码控制请求与响应。实现网络编程。能力不够,API来凑。

AJAX发送请求

XMLHttpRequest:

程序必须先调用 XMLHttpRequest 对象的responseText或responseXML来获取服务器响应,再通过DOM操作将服务器响应动态加载到当前页面中。

关于 XMLHttpRequest 最通用的定义是: XMLHttpRequest是一套可以在JavaScript、VBscript、JScript 等脚本语言中使用的API,它通过HTTP协议异步地向服务器发送请求,并获取从服务器返回的响应。

涉及到 ajax 操作的页面“不能”使用文件协议访问。(不能文件的方式访问)

(我放在了phpstudy_pro里www里的域名为ajax.learn 端口为8080的站点里
所以在网址输入ajax.learn:8080/ajax/ajax1.html即可)

        // 1.安装浏览器(浏览器相当于用户代理)
        // xhr 就类似于浏览器的作用(发送请求接收响应)
        var xhr = new XMLHttpRequest();
        // 2. 打开浏览器,输入网址
        xhr.open('GET', 'time.php');
        // 3. 敲回车,开始请求
        xhr.send();        //在检查里的network中all可查看向服务器请求回的

oneeadystatechange事件中获取响应内容

        // 1.安装浏览器(浏览器相当于用户代理)
        // xhr 就类似于浏览器的作用(发送请求接收响应)
        var xhr = new XMLHttpRequest();
        // 2. 打开浏览器,输入网址
        xhr.open('GET', 'time.php');
        // 3. 敲回车,开始请求
        xhr.send();
        // 4. 等待响应
        // 因为响应需要时间,所以无法通过返回值的方式返回响应 即不能console.log(xhr.send());
        // 因为客户端永远不知道服务端何时才能返回我们需要的响应
        // 所以AJAX API采用事件的机制(通知的感觉)
        xhr.onreadystatechange = function () {
            //这个事件并不是只在响应时触发, 状态改变就触发,(状态改变即创建xhr、open、send)
            console.log(1);   //所以打印了3个1
            console.log(this.readyState);   //2 3 4  因为每个状态对应一个数,0代表创建xhr,1代表open。。。   但是由于事件是后触发的,所以没有打印出全部,
//如果需要捕获第一个状态的变化,需要注意代码执行顺序的问题(不要出现来不及的情况)
        }

time.php

<?php
echo time();
?> 

readyState有五种可能的值:

0 (未初始化): (XMLHttpRequest)对象已经创建,但还没有调用open()方法。

1 (载入):已经调用open() 方法,但尚未发送请求。

2 (载入完成): 请求已经发送完成。

3 (交互):可以接收到部分响应数据。

4 (完成):已经接收到了全部数据,并且连接已经关闭。

        // 1.安装浏览器(浏览器相当于用户代理)
        // xhr 就类似于浏览器的作用(发送请求接收响应)
        var xhr = new XMLHttpRequest();
        console.log(xhr.readyState);   // => 0 初始化,请求代理对象
        // 2. 打开浏览器,输入网址
        xhr.open('GET', 'time.php');
        console.log(xhr.readyState);   // => 1 open方法已经调用,建立一个与服务端特定端口的连接
        // 3. 敲回车,开始请求
        xhr.send();
        // 4. 等待响应
        // 因为响应需要时间,所以无法通过返回值的方式返回响应 即不能console.log(xhr.send());
        // 因为客户端永远不知道服务端何时才能返回我们需要的响应
        // 所以AJAX API采用事件的机制(通知的感觉)
        xhr.onreadystatechange = function () {
            //这个事件并不是只在响应时触发, 状态改变就触发,(状态改变即创建xhr、open、send)
            // console.log(1);   //所以打印了3个1
            // console.log(this.readyState);   //2 3 4
            // switch (this.readyState) {
            //     case 2:
            //         console.log(this.readyState);
            //         // => 2  已经接受到了响应报文的响应头,即服务器名称信息等,但没有接受到响应体
            //         console.log(this.getAllResponseHeaders());  //打印响应头
            //         break;
            //     case 3:
            //         console.log(this.readyState);
            //         // => 3  正在下载响应报文的响应体,有可能为空、或不完整、或完整。
            //         break;
            //     case 4:
            //         console.log(this.readyState);
            //         // => 4  响应体下载完成
            //         break;
            // }
            if (this.readyState !== 4) return;
            //若状态是4,则获取响应的内容
            // console.log(this.readyState);  //4
            console.log(this.responseText);   //1618626395  ,即我们请求的time.php中返回的数据
        }

onload事件

        var xhr = new XMLHttpRequest();
        xhr.open('GET', 'time.php');
        xhr.send();
        
        // onload是HTML5 中提供的XMLHttpRequest version 2.0定义的,跟上述一样的功能
        xhr.onload = function () {
            console.log(this.readyState);   //4
            console.log(this.responseText);  //1618630324
        }

ajax遵循HTTP协议

        var xhr = new XMLHttpRequest();
        xhr.open('POST', 'add.php');  //设置请求行
        xhr.setRequestHeader('Foo', 'Bar');  //设置一个请求头
        // 一定注意 如果请求体是urlencoded格式必须设置这个请求头
        xhr.setRequestHeader('Content-Type', 'application/x-www-form-urlencoded');
        xhr.send('key1=value1&key2=value2');  //以urlencoded 格式设置请求体

add.php

<?php
var_dump($_POST);
?>

数据接口的概念

users1.php

<?php
// 返回的响应就是一个JSON 内容(返回的就是数据)
// 对于返回数据的地址一般我们称之为接口(形式上是Web信息)
$data = array(
    array(
        'id' => 1,
        'name' => '束文波'
    ),
    array(
        'id' => 2,
        'name' => '小夏'
    ),
    array(
        'id' => 3,
        'name' => '米卡'
    ),
    array(
        'id' => 4,
        'name' => '邢克垒'
    )
);
if (empty($_GET['id'])) {
    // 没有传ID,则获取全部
    // 因为HTTP中约定报文的内容就是字符串,而我们需要传递给客户端的信息是-个有结构的数据
    // 这种情况下我们一般采用JSON作为数据格式
    $json = json_encode($data);// 格式:[{"id":1,"name":"束文波"},{...}]
    echo $json; 
} else {
    // 传递了ID,只获取一条
    foreach ($data as $item) {     //循环遍历,
        if ($item['id'] != $_GET['id']) continue;   //找到对应的id对应的数组
        $json = json_encode($item);
        echo $json;   //在地址栏设id=1,则打印出{"id":1,"name":"\u675f\u6587\u6ce2"} ,其中汉字是Unicode格式
    }
}

发送GET请求并传递参数

        var xhr = new XMLHttpRequest();
        // 这里仍然是使用URL中的问号参数传递数据
        xhr.open('GET', 'users.php?id=3');   //users.php在上面 在这里填京东啊,爱奇艺什么的相关数据接口,在下面即可获取内容
        xhr.send(null); 
        xhr.onreadystatechange = function () {
            if (this.readyState !== 4) return;
            console.log(this.responseText);   //{"id":3,"name":"\u7c73\u5361"}
        }

发送GET请求并传递参数—小例子

user2.php

<?php
// 返回的响应就是一个JSON 内容(返回的就是数据)
// 对于返回数据的地址一般我们称之为接口(形式上是Web信息)
$data = array(
    array(
        'id' => 1,
        'name' => '束文波',
        'age' => 26
    ),
    array(
        'id' => 2,
        'name' => '小夏',
        'age' => 24
    ),
    array(
        'id' => 3,
        'name' => '米卡',
        'age' => 23
    ),
    array(
        'id' => 4,
        'name' => '邢克垒',
        'age' => 29
    )
);
if (empty($_GET['id'])) {
    // 没有传ID,则获取全部
    // 因为HTTP中约定报文的内容就是字符串,而我们需要传递给客户端的信息是-个有结构的数据
    // 这种情况下我们一般采用JSON作为数据格式
    $json = json_encode($data);   // 格式: [{"id":1,"name":"张三"},{...}]
    echo $json; 
} else {
    // 传递了ID,只获取一条
    foreach ($data as $item) {     //循环遍历,
        if ($item['id'] != $_GET['id']) continue;   //找到对应的id对应的数组
        $json = json_encode($item);
        echo $json; //在地址栏设id=1,则打印出{"id":1,"name":"\u675f\u6587\u6ce2"} ,其中汉字是Unicode格式
    }
}

实现:点击名字,弹出相应年龄。

<body>
    <ul id="list"></ul>
    <script>
        var listElement = document.getElementById('list');
        // 发送请求获取列表数据呈现在页面
        var xhr1 = new XMLHttpRequest();
        xhr1.open('GET', 'users2.php');
        xhr1.send();
        xhr1.onreadystatechange = function () {
            if (this.readyState !== 4) return;
            //使用 JSON.parse() 方法将请求到的 JSON 数据转换为 JavaScript 对象
            var data = JSON.parse(this.responseText);
            //循环遍历,为每个li注册点击事件
            for (var i = 0; i < data.length; i++) {
                // 创建多个元素li
                var liElement = document.createElement('li');
                // 给li标签设置内容为传过来的name的值
                liElement.innerHTML = data[i].name;
                liElement.id = data[i].id;
                // 把li添加到ul中
                listElement.appendChild(liElement);
                
                // 为li注册点击事件
                listElement.children[i].addEventListener('click', function () {
                    // 需要再请求个数据,返回本次点击的响应的数据
                    var xhr2 = new XMLHttpRequest();
                    // id为本次点击的名字的id
                    xhr2.open('GET', 'users2.php?id=' + this.id);
                    xhr2.send();
                    xhr2.onreadystatechange = function () {
                        if (this.readyState !== 4) return;
                        var data2 = JSON.parse(this.responseText);
                        // 弹出相应名字的年龄
                        alert(data2.age);
                    }
                })
            }
        }

    </script>
</body>

发送POST请求

POST请求过程中,都是采用请求体承载需要提交的数据。

如:

xhr.send(`username=${username}&password=${password}`);

login.php

<?php
// 接收用户提交的用户名和密码
if (empty($_POST['username']) || empty($_POST['password'])) {
    exit('请提交用户名和密码');
}
//校验
$username = $_POST['username'];
$password = $_POST['password'];
if ($username == '蜡笔小新' && $password == 'ilovexiaogege') {
    exit('成功登录');
}
exit('用户名或密码错啦');
?>

实现 点击登录按钮,显示加载层,加载完成后,打印结果

    <style>
        .loading {
            position: fixed;
            top: 0;
            left: 0;
            right: 0;
            bottom: 0;
            background-color: rgb(128, 125, 125);
            opacity: 0.5;
            text-align: center;
            line-height: 500px;
            font-size: 50px;
            display: none;
        }
        .loading::after {
            /*::after用来创建一个伪元素,作为已选中元素的最后一个子元素。这个虚拟元素默认是行内元素。 */
            content: '加载中...';
            color: #fff;
        }
    </style>
</head>
<body>
    <div class="loading" id="loading"></div>
    <table border="1">
        <tr>
            <td>用户名</td>
            <td><input type="text" name="" id="username"></td>
        </tr>
        <tr>
            <td>密码</td>
            <td><input type="password" name="" id="password"></td>
        </tr>
        <tr>
            <td></td>
            <td><button id="btn">登录</button></td>
        </tr>
    </table>
    <script>
        var btn = document.getElementById('btn');
        var txtUsername = document.getElementById('username');
        var txtPassword = document.getElementById('password');
        var loading = document.getElementById('loading');
        // 找一个合适的时机,做一件合适的事情
        btn.onclick = function () {
            //点击登录显示加载中。。。
            loading.style.display = 'block';
            // 1.获取界面上的元素 value
            var username = txtUsername.value;
            var password = txtPassword.value;
            // 2.通过 XHR 发送一个 POST 请求
            var xhr = new XMLHttpRequest();
            xhr.open('POST', 'login.php');
            // 一定注意 如果请求体是urlencoded格式必须设置这个请求头
            xhr.setRequestHeader('Content-Type', 'application/x-www-form-urlencoded');
            xhr.send(`username=${username}&password=${password}`);
            // 3.根据服务端的反馈 做出界面提示
            xhr.onreadystatechange = function () {
                if (this.readyState !== 4) return;
                //加载完成
                loading.style.display = 'none';
                console.log(this.responseText);    // 用户名或密码错啦
            }
        }
    </script>
</body>

同步与异步

同步:一个人在同一个时刻只能做一件事情,在执行一些耗时的操作 ( 需要看管)不去做别的只是等待

异步:在执行一些耗时的操作(不需要看管)去做别的事,而不是等待

一般很少用同步。

        //异步
        console.time('aa');
        var xhr = new XMLHttpRequest();
        // open 方法的第三个参数是async异步 可以传入一个布尔值, 默认为true 
        xhr.open('GET', 'time.php', true);
        xhr.send();
        console.log(xhr.responseText);  // 为空 此时还未获取到完整数据
        // 所以需要:xhr.onreadystatechange = function () 获得完整数据
        console.timeEnd('aa');   // aa: 0.64208984375 ms

        //同步
        console.time('bb');
        var xhr2 = new XMLHttpRequest();
        // open 方法的第三个参数是async异步 可以传入一个布尔值, 默认为true 
        xhr2.open('GET', 'time.php', false);
        xhr2.send();
        // 同步是依次执行,所以不用xhr.onreadystatechange = function () 就能完整接收数据
        console.log(xhr2.responseText);  // 打印出1618828035  
        console.timeEnd('bb');   // bb: 21.026123046875 ms

所以很少用到 同步模式。

响应数据格式

XML

一种数据描述手段

老的东西,简单演示一下,基本现在的项目不用。

淘汰的原因:数据冗余太多

在这里插入图片描述在这里插入图片描述

JSON
也是一种数据描述手段,类似于JavaScript字面量方式
服务端采用JSON格式返回数据,客户端按照JSON格式解析数据。
不管是JSON也好,还是XML,只是在AJAX请求过程中用到,并不代表它们之间有必然的联系,它们只是数据协议罢了

处理响应数据渲染
模板引擎:
artTemplate : https://aui.github.io/art-template/
模板引擎实际上就是一个API, 模板引擎有很多种,使用方式大同小异,目的为了可以更容易的将数据渲染到HTML中

兼容方案:
XMLHttpRequest在老版本浏览器( IE5/6 )中有兼容问题,可以通过另外一种方式代替
var xhr = window. XMLHttpRequest ? new XMLHttpRequest() : new ActiveXobject(‘Mi crosoft.XMLHTTP’)
在这里插入图片描述

<body>
    <table>
        <tbody id="content"></tbody>
    </table>
    <script>
        var xhr = new XMLHttpRequest();
        xhr.open('GET', 'test.php');
        xhr.send();
        xhr.onreadystatechange = function () {
            if (this.readyState !== 4) return;

            var res = JSON.parse(this.responseText);

            var data = res.data;
            for (var i = 0; i < data.length; i++) {
                var tr = document.createElement('tr');
                var td = document.createElement('td');
                //下面方式太麻烦,我们采用模板引擎将数据呈现 artTemplate:https://aui.github.io/art-template/  模板引擎实际上就是一个API
                td.innerHTML = '<td>' + data[i].id + '</td>'  
            }
        }
    </script>
</body>

响应类型

this.response 获取到的结果会根据 this.responseType 的变化而变化
this.responseText 永远获取的是字符串形式的响应体

var xhr = new XMLHttpRequest();
        xhr.open('GET', 'users2.php');
        xhr.send();
        xhr.onreadystatechange = function () {
            if (this.readyState !== 4) return;
            console.log(this);
            console.log(this.response == this.responseText);   //true
        }

若未设置 xhr.responseType = 'json';this.response == this.responseText

若设置:则不相等。

var xhr = new XMLHttpRequest();
        xhr.open('GET', 'users2.php');
        xhr.send();
        xhr.responseType = 'json';
        xhr.onreadystatechange = function () {
            if (this.readyState !== 4) return;
            console.log(this);
        }

在这里插入图片描述

Ajax 基本的封装


    <script>
        function ajax(method, url, params, done) {
            var res = null;
            //若传来的方法是小写,则转化为大写,以便下面判断不出错
            method = method.toUpperCase();

            var xhr = new XMLHttpRequest();

            // 如果params 是个对象,则转换为字符串  {key1:'value1', key2:'value2'}
            if (typeof params == 'object') {
                var tempArr = [];
                for (var key in params) {
                    var value = params[key];
                    tempArr.push(key + '=' + value);
                }   // tempArr => ['key1=value1','key2=value2']
                params = tempArr.join('&');
            }   // params => 'key1=value1&key2=value2'

            if (method == 'GET') {
                url += '?' + params;
            }

            xhr.open(method, url);

            var data = null;
            if (method == 'POST') {
                xhr.setRequestHeader('Content-Type', 'application/x-www-form-urlencoded');
                data = params;
            }

            xhr.send(data);
            xhr.onreadystatechange = function () {
                if (this.readyState !== 4) return;
                // 不应该在封装函数中主观的处理响应结果
                // console.log(this.responseText);
                // 无法在内部包含的函数中通过return 给外部函数调用返回结果
                // return this.responseText;
                // 由于异步模式下,这里的代码最后执行,所以后面res还是=null不等于此结果
                // var res = this.responseText;
                // 把接收到数据后要做的事情给封装者做 
                done(this.responseText);

            }
        }


        function onDone(aa) {
            console.log(aa);
        }

        //调用

        // params 参数是个字符串
        var res = ajax('GET', 'users2.php', 'id=2', onDone);  //{"id":2,"name":"\u5c0f\u590f","age":24}
        ajax('POST', 'login.php', 'username=蜡笔小新&password=ilovexiaogege', onDone);  //成功登录

        // params 参数是个对象
        ajax('GET', 'users2.php', { id: 2 }, onDone);  //{"id":2,"name":"\u5c0f\u590f","age":24}
        ajax('POST', 'login.php', {username: '蜡笔小新', password: 'ilovexiaogege'}, onDone);  //成功登录
    </script>

jQuery中的AJAX

jQuery 中有一套专门针对 AJAX 的封装,功能十分完善,经常使用。

中文文档:https://www.jquery123.com/category/ajax/

<!DOCTYPE html>
<html lang="en">

<head>
    <meta charset="UTF-8">
    <title>Document</title>
</head>

<body>
    <script src="jquery-1.11.3/jquery.js"></script>
    <script>
        // 最基础的调用,最底层的调用
        $.ajax('time.php', {
            type: 'get',   // method 请求方法
            success: function (res) {   //请求成功则执行函数
                // res => 拿到的只是响应体
                console.log(res);   //1619253401 
            }
        })

        // 最常用的调用,最底层的调用
        $.ajax({
            url: 'users2.php',

            type: 'get',   // method 请求方法

            data: { id: 2 },  // 用于提交到服务端的参数,如果是GET请求就通过url传递
            // 如果是POST请求:
            // data: `username=${username}&password=${password}`或 data: { username: username, password: password }

            dataType: 'json',  //当服务端没有设置content-Type时,设此可使得获取的响应体是对象形式,若服务端设content-Type,则此不用写,响应体也是对象形式
            //若两者都没有,则是字符串形式

            beforeSend: function (xhr) {
                // 在所有发送请求的操作(open,send)之前执行
                console.log('未请求', xhr);
            },

            success: function (res) {   // 请求成功则执行函数   只有请求成功(状态码为200)才会执行这个函数
                // 隐藏loading
                // res => 拿到的只是响应体
                console.log(res);   // {id: 2, name: "小夏", age: 24} 
            },

            error: function (xhr) {  //请求不正常
                // 隐藏loading
                // 只有请求不正常(状态码不为200) 才会执行
                console.log('请求失败', xhr);
            },

            complete: function (xhr) {  //请求完成,成功或失败都要执行
                console.log('请求完成', xhr);
            }
        });

        // post请求
        var username = '蜡笔小新'
        var password = 'ilovexiaogege'
        $.ajax({
            url: 'login.php',

            type: 'post',   // method 请求方法

            data: { username: username, password: password },  
            // 或 data: `username=${username}&password=${password}`
            success: function (res) {   // 请求成功则执行函数   只有请求成功(状态码为200)才会执行这个函数
                console.log(res);   // 成功登录 
            },

        });
    </script>
</body>

</html>

jQuery中的快捷方法

				// get方法
        $.get('users2.php', {id: 4}, function (res) {
            console.log(res);   // {id: 4, name: "邢克垒", age: 29}
        });

				var username = '蜡笔小新'
        var password = 'ilovexiaogege'
        // post方法
        $.post('login.php', { username: username, password: password }, function (res) {
            console.log(res);   // 成功登录
        })

        // 使用 AJAX 的 HTTP GET 请求获取 JSON 数据
        $.getJSON('users2.php', {id: 1}, function (res) {
            console.log(res);   //{id: 1, name: "束文波", age: 26}
        } )

jQuery的 load() 方法

load() 方法通过 AJAX 请求从服务器加载数据,并把返回的数据放置到指定的元素中。

**注释:**还存在一个名为 load 的 jQuery 事件方法。调用哪个,取决于参数。

$(selector).load(url,data,function(response,status,xhr))

例:

使用 AJAX 请求来改变 div 元素的文本

$("button").click(function(){
  $("div").load('demo_ajax_load.txt');
});

例子:
请添加图片描述

index.html

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>主页面</title>
    <link rel="stylesheet" href="../nprogress-master/support/style.css">
    <link rel="stylesheet" href="../nprogress-master/nprogress.css">
    <style>
        .loading {
            display: none;
            position: fixed;
            top: 0;
            left: 0;
            bottom: 0;
            right: 0;
            background-color: rgba(0,0,0, .6);     /* 写成.6 少零省空间 */
            font-size: 30px;
        }
    </style>
    <script src="../nprogress-master/nprogress.js"></script>
</head>

<body>
    <!-- 点击链接,在下面只切换main部分,其余不切换。而不用ajax的话,就会整个页面加载切换。 -->
    <h1>会员中心</h1>
    <hr>
    <div class="row">
        <aside class="col-md-3">
            <div class="list-group">
                <a class="list-group-item list-group-item-action" href="index.html">我的资料</a>
                <a class="list-group-item list-group-item-action" href="cart.html">我的购物车</a>
                <a class="list-group-item list-group-item-action" href="orders.html">我的订单</a>
            </div>
        </aside>
        <main id="main" class="col-md-9">
            <h2>姓名:小菜菜。性别:女。电话:1342223442</h2>
            <hr>
        </main>
    </div>
    <div class="loading">正在玩命加载中。。。</div>

    <script src="../jquery-1.11.3/jquery.js"></script>
    <script>
        $(function ($) {

            //原始的方式--------显示加载进度(暗色 正在玩命加载中。。。
            // // 全局事件 
            // $(document)
            // .ajaxStart(function () {
            //     // 只要有ajax 请求发生就会执行
            //     $('.loading').fadeIn();
            //     // 显示加载提示
            //     console.log('注意要开始请求了');
            // })
            // .ajaxStop(function () {
            //     // 只要有ajax 请求结束就会执行
            //     $('.loading').fadeOut();
            //     // 结束提示
            //     console.log('请求结束了');
            // })

            // 用NProgress库--------显示加载进度 (进度条
            $(document)
            .ajaxStart(function () {
                NProgress.start();
            })
            .ajaxStop(function () {
                NProgress.done();
            })

            // 有一个独立的作用域,顺便 确保页面加载完成执行
						// 当连接被点击,则触发事件,执行 加载相应main部分
            $('.list-group-item').on('click', function () {
                var url = $(this).attr('href');
                // 要插入的远程文档的某个部分.如果该字符串中包含一个或多个空格,紧接第一个空格的字符串则是决定所加载内容的 jQuery 选择器
							  // 页面只加载了main部分,其余不加载
                $('#main').load(url + ' #main > *');
                return false;
            })

        })
    </script>
</body>

cart.html

<body>

        <main id="main" class="col-md-9">
            <h2>小猫猫饼干。简爱牛奶。糖糖。</h2>
            <hr>
        </main>
    
</body>

orders.html

<body>
        <main id="main" class="col-md-9">
            <h2>酸奶块块。茶杯。鼠标垫。</h2>
            <hr>
        </main>

</body>

同源策略

相关概念:
同源策略是浏览器的一种安全策略,所谓同源是指域名,协议,端口完全相同,只有同源的地址才可以相互通过AJAX的方式请求。
同源或者不同源说的是两个地址之间的关系, 不同源地址之间请求我们称之为跨域请求

同源策略指的就是:不同源地址之间,默认不能相互发送AJAX请求。
在这里插入图片描述

发送跨域请求的方式

同源策略指的就是:不同源地址之间,默认不能相互发送AJAX请求。

当然我们实际应用有时需要跨域请求。

发送跨域请求的方式 . html

<body>

    <!-- <script src="../jquery-1.11.3/jquery.js"></script> -->
    <script>
        // 发送跨域请求的方法:1.能发出去。2.能收回来

        // 1. img
        // 可以发送不同源地址间的请求,但 不能拿到响应结果。所以不可用 img
        // var img = new Image();
        // img.src = 'https://wx3.sinaimg.cn/mw690/006qB4OBly1gpy3wwacg4j30j60j6mxx.jpg';

        // 2. link
        // 可以发送不同源地址间的请求,但 不能拿到响应结果。所以不可用 img
        // var link = document.createElement('link');
        // link.rel = 'stylesheet';
        // link.href = 'https://wx3.sinaimg.cn/mw690/006qB4OBly1gpy3wwacg4j30j60j6mxx.jpg';
        // document.body.appendChild(link);

        // 3. script
        // 可以发送不同源地址间的请求,但 不能拿到响应结果。
        // 但是 服务端可以返回js代码,当做js执行,就可拿到响应结果,如下:
        var script = document.createElement('script');
        script.src = 'http://localhost/time2.php';
        document.body.appendChild(script);  //开始发起请求,是异步

        
        function foo (res) {
            console.log(res);
        }

        // 请求返回了foo({"time":152242828}),调用foo函数,所以打印出了 {time: 152242828}
    </script>
</body>

time2.php

<?php

// 在HTTP协议消息头中,使用Content-Type来表示请求和响应中的媒体类型信息。
header('Content-Type:application/javascript');

// 当客户端 设置 script.src为此服务端时,因为返回的不是js格式而报错,所以不能这样用json
// echo json_encode(array(
//     'time' => time()
// ));

// 所以输出 js 代码
// echo 'var a = {"time":152242828}';    
// 在客户端打印出错,因为异步,没请求完就打印了,所以我们调用函数把数据呈现。
// 调用客户端的foo()函数
// echo 'foo({"time":152242828})';    

// 当然我们还是要另外的用json
$json = json_encode(array(
    'time' => time()
));

echo "foo({$json})";
  1. JSONP

JSONP的优点就是因为他够老,能兼容各种浏览器,无兼容问题,众生平等。

他发送的不是ajax请求,而是利用了script标签加载机制。他发送的不是ajax请求。

  1. CORS

CORS从具体的代码实现上来说比较方便,前端几乎不需要写任何代码就可以支持。主要是靠服务端进行配置。而且是对各种请求方法、各种数据请求类型都是完美支持的。

CORS需要浏览器和服务器同时支持。目前所有浏览器都支持该功能,IE浏览器不能低于IE10。

整个CORS通信过程,都是浏览器自动完成,不需要用户参与。对于开发者来说,CORS通信与同源的AJAX通信没有差别,代码完全一样。浏览器一旦发现AJAX请求跨源,就会自动添加一些附加的头信息,有时还会多出一次附加的请求,但用户不会有感觉。

因此,实现CORS通信的关键是服务器。只要服务器实现了CORS接口,就可以跨源通信。

JSONP的封装

JSONP的封装.html

<title>JSONP 客户端</title>
</head>

<body>
    <script>
        function jsonp(url, params, callback) {
            // 借助于 script标签发送跨域请求。在客户端借助 script标签请求服务端的一个动态网页( php文件) , 服务端的这个动态网页返回一段带有函数调用的JavaScript
            // 全局函数调用的脚本,将原本需要返回给客户端的数据传递进去。 

            // 为每一个请求创建一个唯一的函数(为防止重名导致出问题)
            // 设置随机数
            var funcName = 'jsonp_' + Date.now() + Math.random().toString().substr(2, 5);

            if (typeof params === 'object') {
                var tempArr = [];
                for (var key in params) {
                    var value = params[key];
                    tempArr.push(key + '=' + value);
                }
                params = tempArr.join('&');
            }

            var script = document.createElement('script');
            script.src = url + '?' + params + '&callback=' + funcName;  // ?callback=' + funcName 是为了告诉服务端需调用的函数名
            document.body.appendChild(script);

            // 定义funcName函数
            // 所有的顶层函数,都可以理解为window的一个方法、[] 跟 . 意义一样
            window[funcName] = function (data) {
                callback(data);
                // 用完后删除
                delete window[funcName];
            }
        }

        // 调用
        jsonp('http://localhost/server.php', { id: 6 }, function (res) {
            console.log(res);
        });
    </script>

</body>
// 使用jQuery实现 (还是JSONP方法实现跨域,只不过代码在jQuery中封装了下)

    <script src="jquery-1.11.3/jquery.js"></script>
    <script>
        $.ajax({
            url: 'http://localhost/server.php',
            dataType: 'jsonp',
            success: function (res) {
                console.log(res);
            }
        })
    </script> 

server.php

<?php
// 从数据库拿数据
$conn = mysqli_connect('localhost', 'root', '123456', 'ban');

$query = mysqli_query($conn, 'select * from yan');

while ($row = mysqli_fetch_assoc($query)) {
    $data[] = $row;
}

// 判断是否传了函数名
if (empty($_GET['callback'])) {
    // 没有就json格式输出在php页面上
    header('Content-Type:application/json');
    echo json_encode($data);
    exit();
}

// 在HTTP协议消息头中,使用Content-Type来表示请求和响应中的媒体类型信息。
header('Content-Type:application/javascript');

$result = json_encode($data);

// 接收函数名
$callback_name = $_GET['callback'];
// echo "ab({$result})";    // 返回js代码 调用ab()函数,此函数在服务端已经定义。  因为是数组,所以用{}

// 返回 js代码--> 调用客户端传来的函数
// //如果$callback_name类型是函数,则输出结果
echo "typeof {$callback_name} === 'function' && {$callback_name}({$result})";

ajax跨域资源共享(CORS)

JSONP是早年跨域请求的方式,我们现在有了 CORS 实现跨域请求。

JSONP的优点 就是因为他够老,能兼容各种浏览器,无兼容问题,众生平等。他发送的不是ajax请求,而是利用了script标签加载机制。他发送的不是ajax请求。

CORS 从具体的代码实现上来说比较方便,前端几乎不需要写任何代码就可以支持。主要是靠服务端进行配置。而且是对各种请求方法、各种数据请求类型都是完美支持的。

CORS需要浏览器和服务器同时支持。目前所有浏览器都支持该功能,IE浏览器不能低于IE10。

整个CORS通信过程,都是浏览器自动完成,不需要用户参与。对于开发者来说,CORS通信与同源的AJAX通信没有差别,代码完全一样。浏览器一旦发现AJAX请求跨源,就会自动添加一些附加的头信息,有时还会多出一次附加的请求,但用户不会有感觉。

因此,实现CORS通信的关键是服务器。只要服务器实现了CORS接口,就可以跨源通信。

ajax跨域资源共享(CORS).html

<body>

    <script src="jquery-1.11.3/jquery.js"></script>
    <script>
        // 跨域请求时,客户端不需要做任何设置
        // 服务端只需设置 header('Access-Control-Allow-Origin: *');  
        $.get('http://localhost/cors.php', {}, function (res) {
            console.log(res);
        })

    </script>
</body>

cors.php

<?php
// 从数据库拿数据
$conn = mysqli_connect('localhost', 'root', '123456', 'ban');

$query = mysqli_query($conn, 'select * from yan');

while ($row = mysqli_fetch_assoc($query)) {
    $data[] = $row;
}

// 跨域请求时,客户端不需要做任何设置
// 服务端只需设置 header('Access-Control-Allow-Origin: *');

// 一行代码实现跨域
// 允许所有的源对我发起请求
header('Access-Control-Allow-Origin: *');
// 允许某源对我发起请求
// header('Access-Control-Allow-Origin: 具体地址');  

header('Content-Type: application/json');
echo json_encode($data);
  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

欢莱

为您解决问题,此项目我成功完成

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值