Ajax_简介: 异步的 JS 和 XML_原生写 ajax 分析其原理_jquery_ajax_art-template

AJAXjavascript

Asynchronous JavaScript And XMLcss

经过 AJAX 能够在 浏览器中向 服务器 发送异步请求html

一种 使用现有标准的 新方法,而非新语言前端

  • XML 

可扩展标记语言java

被设计用来传输和存储数据node

被 JSON 替代,JSON 内容更少,解析更方便jquery

和 HTML 相似,不一样的是git

  • HTML 都是预约义标签
  • XML 所有是自定义标签,用来表示一些数据
  • AJAX 工做原理

至关于在 用户 和 服务器 之间加了一个中间层(AJAX 引擎)github

使得 用户操做 和 服务器响应 异步化web

1. 原生 AJAX(不要经过 webstorm 启动页面,不然会发生 跨域 错误)

// 1. 建立 xhr 对象

const xhr = new XMLHttpRequest();

// 2. 设置事件监听

xhr.onreadystatechange = function(){    // 会监听 readyState 值的变化

if (xhr.readyState === 2) {

console.log(xhr.status);
console.log(xhr.getResponseHeader('Content-Type'));

}
if (xhr.readyState === 3) {

console.log(xhr.responseText);

}

if(xhr.readyState === 4 && xhr.status === 200){    // 响应成功

console.log(xhr.responseText);    // 响应数据

};

};

/****

前端面试题:

readyState

0        xhr 对象建立成功,可是 xhr.open() 还未调用

1        open() 已经调用了,可是还未调用 send() (意味着尚未发送请求,还能够设置请求头信息)

2        send() 已经调用了,接收到部分响应数据(响应首行、响应头,没接到响应体)

3        接收到了响应体数据(若是响应体较小,或者纯文体,在此阶段就所有接收完了)

4        接收彻底部的响应体数据(数据较大,或者音视频资源)

****/

// 3. 设置请求信息    设请求方式、地址、参数

xhr.open("GET", "http://localhost:3000/ajax?username=jack&age=18");

// 还能设置请求头 xhr.setRequestHeader();

xhr.setRequestHeader('content-type', 'application/x-www-form-urlencoded');

/****

必需要设置 请求头 标准规范(有三种常见规范),不然不会解析请求参数

chrome 和 FireFox    第二次及之后默认走协商缓存,状态码 304,且还会向服务器发送请求

ie    第二次及之后 get 请求 默认走强制缓存,状态码 200,且不会向服务器发送请求

需求: 股票 须要实时更新信息,此时就不能从缓存里找

解决 ie 的缓存问题:

让每一次的请求不同

只要请求不同,就不会走缓存

xhr.open("GET", "http://localhost:3000/ajax?username=jack&age=18&date="+Date.now());

****/

// 4. 发送请求

xhr.send();

// post 发送数据 必须以 urlencode 格式,即查询字符串去掉?,即 key=value的方式,多个键值对之间以 & 链接

  • 源码实例
  • node.js 服务器

index.js

  • const express = require('express'); const app = express(); app.use(express.static("public")); app.use(express.urlencoded({extended: true})); app.get("/", (request, response)=>{ response.sendFile("./public/idnex.html"); }); // 原生 ajax 的 get 路由
    app.get("/ajax", (request, response)=>{ console.log('----get 接收的 浏览器数据: '); console.log(request.query); // {} console.log(request.body); // get 请求体 始终为空 console.log('----'); response.send({name: '服务器 get 响应', line: 15}); }); // 原生 ajax 的 post 路由
    app.post("/ajax", (request, response)=>{ console.log('----post 接收的 浏览器数据: '); console.log(request.query); // {} 能够有 请求字符串 console.log(request.body); // post请求体 数据{ username: 'jack', age: '18' } console.log('----'); response.send({name: '服务器 post 响应', line: 21}); }); /**************** 端口号 3000, 启动服务器 ***************/ app.listen(3000, err=>console.log(err?err:'\n\n服务器已启动: http://localhost:3000\n\t\tHunting Happy!'));
  • 浏览器前端代码

index.html

  • <!DOCTYPE html> <html> <head> <meta charset="UTF-8"/> <title>原生 ajax</title> </head> <body> <button id="get_btn">get</button> <button id="post_btn">post</button>

    <script type="text/javascript" src="js/index.js"></script> </body> </html>

js/index.js

  • window.addEventListener('DOMContentLoaded', function () { const getBtn = document.getElementById("get_btn"); const postBtn = document.getElementById("post_btn"); getBtn.onclick = function () { // 1. 建立 xhr 对象 const xhr = new XMLHttpRequest(); // 2. 设置事件监听 xhr.onreadystatechange = function () { if (xhr.readyState === 2) { console.log(xhr.status); // 状态码 console.log(xhr.getResponseHeader('Content-Type')); // 请求头 信息  }; if (xhr.readyState === 3) { console.log(xhr.responseText); // 服务器响应 数据  }; if(xhr.readyState === 4 && xhr.status === 200){ console.log(xhr.responseText); // 服务器响应 数据  }; }; // 3. 设置请求方式、请求地址、请求参数 xhr.open("GET", "http://localhost:3000/ajax?username=get&get=get"); // 4. 设置请求头 xhr.setRequestHeader('get-x', 'get'); // 5. 发送请求 xhr.send('request=get&get=get'); // get 请求体为空,因此这里传的参数,无效 }; postBtn.onclick = function () { // 1. 建立 xhr 对象 const xhr = new XMLHttpRequest(); // 2. 设置事件监听 xhr.onreadystatechange = function () { if (xhr.readyState === 2) { console.log(xhr.status); console.log(xhr.getResponseHeader('Content-Type')); } if (xhr.readyState === 3) { console.log(xhr.responseText); } if(xhr.readyState === 4 && xhr.status === 200){ console.log(xhr.responseText); }; }; // 3. 设置请求方式、请求地址、请求参数 xhr.open("POST", "http://localhost:3000/ajax?username=post&post=post"); // 4. 设置请求头 xhr.setRequestHeader('content-type', 'application/x-www-form-urlencoded'); // 5. 发送请求 xhr.send('request=post&post=post'); }; }, false);

2. jQuery 中的 AJAX 请求

  • node.js 服务器

index.js

  • const express = require('express'); const app = express(); app.use(express.static("public")); app.use(express.urlencoded({extended: true})); app.get("/", (request, response)=>{ response.sendFile("./public/idnex.html"); }); // 原生 ajax 的 get 路由 app.get("/jquery_ajax", (request, response)=>{ console.log('----get 接收的 浏览器数据: '); console.log(request.query); // {} console.log(request.body); // get 请求体 始终为空 console.log('----'); response.send({name: '服务器 get 响应', line: 15}); }); // 原生 ajax 的 post 路由 app.post("/jquery_ajax", (request, response)=>{ console.log('----post 接收的 浏览器数据: '); console.log(request.query); // {} 能够有 请求字符串 console.log(request.body); // post请求体 数据{ username: 'jack', age: '18' } console.log('----'); response.send({name: '服务器 post 响应', line: 21}); }); /**************** 端口号 3000, 启动服务器 ***************/ app.listen(3000, err=>console.log(err?err:'\n\n服务器已启动: http://localhost:3000\n\t\tHunting Happy!'));
  • 浏览器前端代码

index.html

  • <!DOCTYPE html> <html> <head> <meta charset="UTF-8"/> <title>jQuery 中的 ajax</title> </head> <body> <button id="get_btn">get</button> <button id="post_btn">post</button>  <script type="text/javascript" src="https://cdn.bootcss.com/jquery/1.12.4/jquery.min.js"></script> <script type="text/javascript" src="js/jquery_ajax.js"></script> </body> </html>

index.js

  • window.addEventListener('DOMContentLoaded', function () { const getBtn = document.getElementById("get_btn"); const postBtn = document.getElementById("post_btn"); getBtn.onclick = function () { $.ajax('http://localhost:3000/jquery_ajax', { method: 'GET', // 能够直接换成 POST,库解决好了请求头和兼容等一系列问题  data: { getrequest:'Browser', age:10 }, headers: { 'get-xxx': 'xxxx' }, success: function (server_info) { console.log('请求成功的回调函数'); console.log(server_info); // 自动将 json 字符串 转换成 JSON 对象  }, error: function (err) { console.log('请求失败的回调函数'); console.log(err); } }); }; postBtn.onclick = function () { $.get( // 能够直接换成 post,库解决好了请求头和兼容等一系列问题 'http://localhost:3000/jquery_ajax', {postrequest:'Browser', age:26}, function (server_info) { console.log(server_info); }); }; }, false);

三级联动 选择(省-市-县)

  • 服务器 index.js
  • const express = require('express');
    const promiseConnect = require('./db/connectDB.js');
    const citiesModel = require('./models/userModel.js');
    const app = express();
    
    (async ()=>{
        const ret = await promiseConnect;
        console.log(ret);
        
        app.use(express.static("public"));
        app.use(express.urlencoded({extended: true}));
        
        app.get("/", (request, response)=>{
            response.sendFile("./public/index.html");
        });
    
        // 省 的 get 路由
        app.get("/province", async (request, response)=>{
            try{
                const province = await citiesModel.find({"level": 1}, {"province": 1, "name": 1, "_id": 0});
                response.json({code: 200, data: province});
            }catch(err){
                console.log(err);
                response.json({code: 404, data: '网络不稳定,请刷新重试'});
            };
        });
        
        // 市 的 get 路由
        app.get("/city", async (request, response)=>{
            try{
                const {province} = request.query;
                const city = await citiesModel.find({province, "level": 2}, {"city": 1, "name": 1, "_id": 0});
                response.json({code: 200, data: city});
            }catch(err){
                console.log(err);
                response.json({code: 404, data: '网络不稳定,请刷新重试'});
            };
        });
        
        // 县 的 get 路由
        app.get("/county", async (request, response)=>{
            try{
                const {province, city} = request.query;
                const county = await citiesModel.find({province, city, "level": 3}, {"county": 1, "name": 1, "_id": 0});
                response.json({code: 200, data: county});
            }catch(err){
                console.log(err);
                response.json({code: 404, data: '网络不稳定,请刷新重试'});
            };
        });
    })().catch(err=>console.log(err));
    
    /**************** 端口号 3000, 启动服务器 ***************/
    app.listen(3000, err=>console.log(err?err:'\n\n服务器已启动: http://localhost:3000\n\t\tHunting Happy!'));
  • 浏览器前端 index.html
  • <!DOCTYPE html>
    <html>
        <head>
            <meta charset="UTF-8"/>
            <title>三级联动-省-市-县</title>
            <link rel="stylesheet" href="./css/index.css">
        </head>
        
        <body>
            <div id="outer_box">
                <select id="province">
                    <option>请选择省份</option>
                </select><select id="city">
                    <option>请选择市</option>
                </select><select id="county">
                    <option>请选择区(县)</option>
                </select>区(县)
            </div>
            
            
            
            <script type="text/javascript" src="https://cdn.bootcss.com/jquery/1.12.4/jquery.min.js"></script>
            <script type="text/javascript" src="./js/jquery_ajax.js"></script>
        </body>
    </html>

index.css

  • html, body {
        width: 100%;
        height: 100%;
        
        color: #000;
        background: #b9c2a4;
        background-size: cover; /* 指定背景图片大小 */
    }
    
    /*************************************************/
    #outer_box {
        width: 100%;
        height: 100%;
        display: flex;
        justify-content: center;
        align-items: center;
    }
    
    #outer_box select {
        width: 152px;
        font-size: 16px;
        background-color: #aec57e;
        cursor: pointer;
    }
  • 选择省份

为了不重排 重绘,使用拼串,最后一次追加

  • 选择市

监听 表单的 change 事件

  • 选择县
  • jquery_ajax.js
  • $(function () {
        const $province = $("#province");
        const $city = $("#city");
        const $county = $("#county");
        
        // 进入页面 首先渲染省份
        $.get("http://localhost:3000/province", function({code, data}){
            if(code === 200){
                let htmlStr = '<option>请选择省份</option>';
                data.forEach(each=>{
                    /* <option value="44">广东省</option> */
                    htmlStr += `<option value="${each.province}">${each.name}</option>`;
                });
                $province.html(htmlStr);
            }else{
                alert(data);    // 网络不稳定,请刷新重试
            };
        });
        
        // 省 改变出现 市
        $province.on("change", function(){
            const province = this.value;    /* <option value="11">北京</option> */
            $.get('/city', {province}, function({code, data}){
                if(code === 200){
                    let htmlStr = '<option>请选择市</option>';
                    data.forEach(each=>{
                        /* <option value="03">深圳市</option> */
                        htmlStr += `<option value="${each.city}">${each.name}</option>`;
                    });
                    $city.html(htmlStr);
                }else{
                    alert(data);    // 网络不稳定,请刷新重试
                };
            });
        });
        
        // 市 改变出现 县
        $city.on("change", function(){
            const province = $province.val();    /* <option value="11">北京</option> */
            const city = $city.val();    /* <option value="undefined">鞍山市</option> */
            console.log({province, city});
            $.get('/county', {province, city}, function({code, data}){
                if(code === 200){
                    let htmlStr = '<option>请选择市</option>';
                    data.forEach(each=>{
                        /* <option value="06">宝安区</option> */
                        htmlStr += `<option value="${each.county}">${each.name}</option>`;
                    });
                    $county.html(htmlStr);
                }else{
                    alert(data);    // 网络不稳定,请刷新重试
                };
            });
        });
    });

在 jQuery 中 $.get("http://localhost:3000/city", function({code, data}){}); 对于同一域名,能够简写为

  • $.get("/city", function({code, data}){});

1. 引入 第三方 js库 art-template

<script type="text/javascript" src="./js/template-web.js"></script>

2. 新建 <script> 标签,并设置 id 以供渲染

3. 

源码由上方代码改变

  • index.html
  • <!DOCTYPE html>
    <html>
        <head>
            <meta charset="UTF-8"/>
            <title>jQuery 中的 ajax</title>
            <link rel="stylesheet" href="./css/index.css">
        </head>
        
        <body>
            <div id="outer_box">
                <select id="province">
                    <option>请选择省份</option>
                </select>省
            
                <select id="city">
                    <option>请选择市</option>
                </select>市
            
                <select id="county">
                    <option>请选择区(县)</option>
                </select>区(县)
            </div>
        
            <script type="text/html" id="templateScript"> <option>{{firstOption}}</option> {{each data}} <option value="{{$value[name]}}">{{$value.name}}</option> {{/each}} </script>
            
            
            
            
            <script type="text/javascript" src="https://cdn.bootcss.com/jquery/1.12.4/jquery.min.js"></script>
            <script type="text/javascript" src="./js/template-web.js"></script>
            <script type="text/javascript" src="./js/jquery_ajax.js"></script> <!-- 注意编写顺序 -->
        </body>
    </html>
  • jquery_ajax.js
  • $(function () {
        const $province = $("#province");
        const $city = $("#city");
        const $county = $("#county");
        
        // 进入页面 首先渲染省份
        $.get("http://localhost:3000/province", function({code, data}){
            if(code === 200){
                const htmlStr = template( 'templateScript', {data, firstOption: '请选择省份', name: 'province'} );
                $province.html(htmlStr);
            }else{
                alert(data);    // 网络不稳定,请刷新重试
            };
        });
        
        // 省 改变出现 市
        $province.on("change", function(){
            const province = this.value;    /* <option value="11">北京</option> */
            $.get('/city', {province}, function({code, data}){
                if(code === 200){
                    const htmlStr = template( 'templateScript', {data, firstOption: '请选择市', name: 'city'} );
                    $city.html(htmlStr);
                }else{
                    alert(data);    // 网络不稳定,请刷新重试
                };
            });
        });
        
        // 市 改变出现 县
        $city.on("change", function(){
            const province = $province.val();    /* <option value="11">北京</option> */
            const city = $city.val();    /* <option value="undefined">鞍山市</option> */
            $.get('/county', {province, city}, function({code, data}){
                if(code === 200){
                    const htmlStr = template( 'templateScript', {data, firstOption: '请选择区县', name: 'county'} );
                    $county.html(htmlStr);
                }else{
                    alert(data);    // 网络不稳定,请刷新重试
                };
            });
        });
    });