前端与移动开发----Ajax编程----原生JS代码Ajax使用,自己封装Ajax,表单的提交

Ajax编程

回顾

  1. 什么是网络?

    用网线/无线信号 - 链接在一起的各种电脑形成网络

  2. 什么是资源?

    数据, 字符串, 文件, 视频, 音频等等, 存储在电脑上的。

  3. 服务器和客户端

    客户端负责浏览和使用各种资源的设备(个人电脑/个人手机等等)

    服务器负责提供各种数据资源

  4. URL

    客户端想要去请求资源, 需要知道资源在哪里. 所以URL是一串地址, 标记资源在哪里. (叫统一资源定位符)

  5. IP

    URL中开头部分, 用于标识网络中哪台计算机的地址

  6. 域名

    ip是一串以.分割的4段数字, 很难记住, 所以我们有了域名(一串.分割的英文字符)

  7. DNS服务

    负责记录域名和IP的对应关系, 用于把域名翻译成IP地址的功能, 负责在网络里寻找目标电脑的IP

  8. 请求响应过程

    客户端 -> 请求 -> 服务器

    客户端 <- 响应 <- 服务器

  9. 请求的分类

    • 非Ajax - 比如打开一个网页, 网页直接把数据全都加载回来
    • Ajax请求 - 是一种异步请求资源的方式(不用刷新整个网页, 就可以给网页某一块从后端请求数据)
  10. Ajax请求方式

    在JS代码中, 编写一段代码就可以在html网页中嵌入一个请求的方式, 返回的数据到JS代码的地方

  11. 必备能力

    学会从Network里分析网络请求(跟css / console打印一样)

  12. 请求方式

    • GET - 是请求数据 - 负责从后台GET拿数据
    • POST - 用于发送数据 - 把前端的数据发送给后台
  13. 使用Ajax

    $.ajax({

    ​ type: “”, // 请求方式 - 默认不写是GET(大小写都可以)

    ​ url: “”, // 请求的后端地址

    ​ data: {}, // 里面可以向后台传递数据

    ​ success: function(res){} // 固定是一个函数题(用于接受后台返回的结果

    })

  14. 后端接口

    就是使用的URL: 只不过这个url返回的不是网页, 而是一串字符串数据

  15. 接口调试工具

    • 不用写$.ajax 就可以测试下 后台的URL是否可用
    • 可使用postman / REST Client插件来测试URL是否可用

4. 原生JS代码 - Ajax使用

之前用的是JQ封装的Ajax功能, 这节课我们来看看内部实现的原理

4.0 JS - Ajax编写

// 1. 实例化ajax对象
var ajaxObj = new XMLHttpRequest(); 

// 2. 注册 onreadystatechange 事件
/*
          下面事件的触发时机, ajax对象的readyState状态改变时触发
          0 - ajax对象被创建 
          1 - open一定被调用
          2 - send一定被调用
          3 - 正在接收服务器数据
          4 - 服务器数据接收完毕
          当0变到1, 触发一次onreadystatechange事件, 当1到2, 当2到3, 当3到4都会触发onreadystatechange事件执行
        */
// ajax(XMLHttpRequest) 让浏览器发起一次 -> http网络请求
ajaxObj.onreadystatechange = function () {
     
    // 4(数据接收完毕)(JS代码层面), status代表http网络请求成功(200)
    if (ajaxObj.readyState === 4 && ajaxObj.status === 200) {
     
        // responseText 取出请求回来的字符串数据
        var res = JSON.parse(ajaxObj.responseText);
        console.log(res);
    }
}

// 3. 调用open方法,设置请求方式及请求的url地址
ajaxObj.open('GET', 'URL');

// 4. 最后,调用send方法,发送这次ajax请求
ajaxObj.send();

readyState属性和onreadystatechange事件

Ajax从创建xhr对象开始,一直到完全接收服务器返回的结果为止;我们可以把整个请求响应过程划分为几个阶段。

请求阶段 - 异步等待阶段 - 响应阶段

  • Ajax对象 - 执行send()方法 - 就进入请求发送阶段
  • 浏览器开启线程去指定的URL请求数据, 后台收到请求, 执行后台代码, 然后返回数据
  • Ajax对象 - 事件监听收到返回的数据出发事件和回调函数执行

4.1 JS - Ajax - GET请求

  • 参数和前面的接口地址之间,使用 ? 隔开
  • 如果有多个参数,参数之间使用 & 隔开
  • 多个参数之间,没有顺序要求

在url后面拼接的请求参数,就是 “xxx=sss&yyy=mmm&zzz=bbb” 这种格式的字符串,叫做查询字符串

// 1. id为3的书籍信息
// 1.1 创建Ajax对象 - 绑定状态改变事件(准备接受返回的数据)
var ajax = new XMLHttpRequest();
ajax.onreadystatechange = function () {
     
    if (ajax.readyState === 4 && ajax.status === 200) {
     
        var res = JSON.parse(ajax.responseText);
        console.log(res);
    }
}

// 1.2 设置请求方式, 请求的url以及参数
ajax.open('GET', 'URL?id=3');
// 1.3 发送请求
ajax.send();


// 2. id为1且bookname是西游记
// 2.1 再创建一个Ajax对象
var ajaxObj = new XMLHttpRequest();
// 2.2 绑定事件
ajaxObj.onreadystatechange = function () {
     
    if (ajaxObj.readyState === 4 && ajaxObj.status === 200) {
     
        var res = JSON.parse(ajaxObj.responseText);
        console.log(res);
    }
}
// 2.3 设置请求方式 - 请求url - 参数拼接
ajaxObj.open('GET', 'URL?bookname=西游记&id=1');
// 2.4 发送请求
ajaxObj.send();

前端与移动开发----Ajax编程----原生JS代码Ajax使用,自己封装Ajax,表单的提交_第1张图片

4.2 url编码

// 编码: 计算机保存/传输一切都是以0和1位基本的, 给我们展示的时候, 就得转换编程成另一种形式
// url编码: 把url地址中的非英文字符转成另外一种编码形式, 确保后台准确解析我通过url的参数

// 方法1: 快速编码和解码
console.log(encodeURI('西游记&')); // %E8%A5%BF%E6%B8%B8%E8%AE%B0&
console.log(decodeURI('%E8%A5%BF%E6%B8%B8%E8%AE%B0&'));// 西游记& 

// 方法2: 范围更广的 编码 和 解码
console.log(encodeURIComponent('西游记&')); // %E8%A5%BF%E6%B8%B8%E8%AE%B0%26
console.log(decodeURIComponent('%E8%A5%BF%E6%B8%B8%E8%AE%B0%26')); // 西游记&

// 方法2, 可以编码的字符比较多
// 可以对 ;/?:@&=+$,# 进行编码
// 两个函数都不会对  - _ . ! ~ * ' ( ) 进行编码

4.3 url编码使用场景

// 使用场景:
// 问题:
// 我们都知道url传递的格式是key=value&key=value
// 但是当我的值里也出来了&, 就破坏了解析字符串的规则, 后台解析失败

// 1.1 创建 Ajax对象
var ajax = new XMLHttpRequest();
ajax.onreadystatechange = function () {
     
    if (ajax.readyState === 4 && ajax.status === 200) {
     
        var res = JSON.parse(ajax.responseText);
        console.log(res);
    }
}

// 1.2 设置请求方式, 请求的url以及参数
ajax.open('GET', 'URL?a=6&10');
// 1.3 发送请求
ajax.send();

// 解决: 进行url编码
var str = encodeURIComponent("6&10");
console.log(str);
var ajax = new XMLHttpRequest();
ajax.onreadystatechange = function () {
     
    if (ajax.readyState === 4 && ajax.status === 200) {
     
        var res = JSON.parse(ajax.responseText);
        console.log(res);
    }
}

// 1.2 设置请求方式, 请求的url以及参数
ajax.open('GET', `URL?a=${
       str}`);
// 1.3 发送请求
ajax.send();

4.4 JS - Ajax - POST请求

和GET请求的两个区别

  • 请求参数位置不一样
  • 需要多加一个请求头
document.getElementById("createBtn").onclick = function () {
     
    // 1.1 创建Ajax对象 - 监测事件
    var ajax = new XMLHttpRequest();
    ajax.onreadystatechange = function () {
     
        if (this.readyState === 4 && this.status === 200) {
     
            var res = JSON.parse(this.responseText);
            console.log(res);
        }
    }
    // 1.2 设置请求方式 - 请求的url
    ajax.open('POST', 'URL');


    // // 必须在open和send之间加一个请求头,这个请求头写法固定。记不住可以复制
    // 1.3 设置请求头 - 告诉后端, 我给你发送的内容类型
    // 意思是以xxx=yyy&zzz=ttt的格式传递参数给后台, 后台从Content-type发现值是下面这个就按照对应的规则来解析这个字符串, 提取参数名和值了
    ajax.setRequestHeader('Content-Type', 'application/x-www-form-urlencoded');

    // 1.4 发送请求并且携带参数, 格式固定
    // POST方式提交的数据,仍然是查询字符串格式,只不过位置改变了
    ajax.send('bookname=红与黑&author=司汤达&publisher=法国出版社&appkey=b7fc2560-5632-4da5-b625-58cff58c6b31');
}

4.5 练习

练习1: 编写原生Ajax代码 - 请查询公共数据(无需带appkey参数), 中id为2的数据信息 (这是要哪数据吧? 用那种请求方式呢?)
        let ajaxObj = new XMLHttpRequest();
        ajaxObj.onreadystatechange = function(){
     
            if (ajaxObj.readyState == 4) {
     
                if (ajaxObj.status == 200) {
     
                    console.log(ajaxObj.responseText);
                }
            }
        }
        // 总结: 多个参数要在?后面 以参数名=值&参数名=值
        ajaxObj.open("GET", "URL?id=2");
        ajaxObj.send();
练习2: 编写原生Ajax代码 - 请向自己的表中(带appkey和自己的值), 向后台随便增加一条书籍信息, 然后调用查询自己书籍信息的接口, 查看是否添加成功 - (这是要发送数据吧? 应该用什么请求方式呢?)
        // 1. 实例化ajax对象
        let ajaxObj = new XMLHttpRequest();
        // 2. 绑定事件
        ajaxObj.onreadystatechange = function(){
     
            // 5. 接受返回的结果
            if (ajaxObj.readyState == 4) {
     
                if (ajaxObj.status == 200) {
     
                    console.log(ajaxObj.responseText);
                }
            }
        }
        // 3. 设置参数
        ajaxObj.open("POST", "URL");

        // (新) - 设置内容的类型
        ajaxObj.setRequestHeader("Content-Type", "application/x-www-form-urlencoded");

        // 4. 发送请求
        // (新)-post的参数要写在send()里面
        ajaxObj.send("bookname=我是vscode插件的书籍&author=vscode&publisher=121&appkey=b7fc2560-5632-4da5-b625-58cff58c6b31");

整体

  • 无论是GET还是POST方式,请求参数如有特殊字符, 最好进行urll编码
  • 服务器返回的一般都是JSON格式的字符串,需要自己调用 JSON.parse 转换格式
  • GET还是POST用哪种, 其实和后台规定的对应上即可
  • 参数名一定也要和后台规定的对应上即可

5. 自己封装Ajax

来模拟下JQ的ajax的函数内代码的执行过程

		// function $(){};
        // $.ajax = function(){};
        // $.ajax();
        // 封装函数的过程步骤:
        // 1. 定义函数壳子(名字)
        // 2. 调用函数, 传入一套例子(目标)
        // 3. 编写(粘贴+修改)函数里的代码
        //   想好哪些变量以后会变 (这次传a, 下次传b, 那么这个变量就必须在形参上)

        function myAjax(obj) {
     
            // 解构赋值提取外面参数的值
            let {
      type, url, data, success } = obj;
            // 原生Ajax
            let ajaxObj = new XMLHttpRequest();
            ajaxObj.onreadystatechange = function () {
     
                if (ajaxObj.readyState == 4) {
     
                    if (ajaxObj.status == 200) {
     
                        success(JSON.parse(ajaxObj.responseText)); // 回调外面传入的success对应的函数执行, 把值传出去
                    }
                }
            }
            ajaxObj.open(type, url);
            ajaxObj.setRequestHeader("Content-Type", "application/x-www-form-urlencoded");
            // 把对象转成字符串
            // 不能用JSON.stringify, 因为字符串的格式不对, 我们要的是key=value&key=value的字符串
            var arr = [];  // 因为对象里有多对key=value, 所以我想要把对象没对key-value转成字符串, 多对都转在一个数据结构里(采用数组来装载)
            for (var key in data) {
     
                arr.push(`${
       key}=${
       data[key]}`);
            }
            var argStr = arr.join("&"); // join就是用()里的符号, 把数组里的每个值链接起来形成一个大字符串返回
            ajaxObj.send(argStr);
        }
        myAjax({
     
            type: "POST",
            url: "http://123.57.109.30:3006/api/addbook",
            data: {
     
                bookname: "我是vscode插件的书籍",
                author: "vscode",
                publisher: "哈哈",
                appkey: "b7fc2560-5632-4da5-b625-58cff58c6b31"
            },
            success: function (res) {
     
                console.log(res);
            }
        })"
            },
            success: function (res) {
     
                console.log(res);
            }
        })

5.0 自己实现$.ajax() 方法

回忆下$.ajax里传入的配置对象, 有哪些key属性和功能

  • get方式: 传参 和不传参
  • post方式: 传参

封装思路

  • 获取对象的属性(可选)
  • 基本的Ajax代码(基本的步骤写出来)
  • 判断GET和POST请求,分别写 open 和 send方法
  • 处理请求参数,把对象形式的参数处理成查询字符串格式
  • 当ajax请求成功之后,调用success函数,把服务器返回的结果传入
  • 细节处理(默认GET方式、不区分大小写等等…)

使用自己封装的Ajax方法

function $() {
      };
$.ajax = function (obj) {
     
    // 1. 默认值确保
    obj.type = obj.type || "GET"; // 防止外面没传type值, 给予默认值"GET"
    obj.type = obj.type.toUpperCase(); // 防止外面传的小写, 导致下面比较不相等
    // 模拟JQ的ajax实现过程 - 内部使用的就是原生JS的XMLHTTPRequest

    // 2. 新建Ajax对象 - 绑定事件
    var ajax = new XMLHttpRequest();
    ajax.onreadystatechange = function () {
     
        if (this.readyState === 4 && this.status === 200) {
     
            obj.success(JSON.parse(this.responseText)) // 请求成功回调外面success函数执行, 把值传出去
        }
    }
    // 3. 把data对象里的参数转换成这个格式 key=value&key=value
    var arr = [];
    for (var prop in obj.data) {
     
        arr.push(`${
       prop}=${
       obj.data[prop]}`);
    }
    var argStr = arr.join("&"); // 拼接字符串参数

    // 4. 判断是不是GET方式, 并且是否有参数, 都符合在拼接url后面?传参
    if (obj.type == "GET") {
     
        obj.url += "?" + argStr; // 注意这里必须是+=哦
    }
    // 5. 设置Ajax请求方式和url
    ajax.open(obj.type, obj.url);

    // 6. 判断是POST, 得设置请求头内容类型
    obj.type.toUpperCase() == "POST" && ajax.setRequestHeader('Content-Type', 'application/x-www-form-urlencoded'); // 判断type是POST方式, 则必须执行设置请求头的内容类型

    // 7. 发起Ajax请求
    ajax.send(obj.type == "POST" ? argStr : '');
}
// 点击查询
document.getElementById("btn").onclick = function () {
     
    $.ajax({
     
        url: 'http://123.57.109.30:3006/api/getbooks',
        data: {
     
            appkey: "b7fc2560-5632-4da5-b625-58cff58c6b31"
        },
        success: function (res) {
     
            console.log(res);
        }
    })
}

// 点击新增
document.getElementById("createBtn").onclick = function(){
     
    $.ajax({
     
        type: "post",
        url: 'http://123.57.109.30:3006/api/addbook',
        data: {
     
            bookname: "红黑树",
            author: "算法杨",
            publisher: "数学出版社",
            appkey: "b7fc2560-5632-4da5-b625-58cff58c6b31"
        },
        success: function (res) {
     
            console.log(res);
        }
    })
}

6. 表单的提交

以前没有Ajax的时候, 都是用表单向后台提交数据

6.0 表单的同步提交(了解)

点击 类型的按钮或者在form标签里的button,让表单自行提交到 action 指定的url位置。这就是表单的同步提交。

同步提交的缺点:

  • 页面会跳转,用户体验差
  • 表单提交之后,表单中填写的数据,可能就丢失了,得重新填写

from标签的action、method、enctype、target只有在表单同步提交的时候才有用

  • action 是 form标签提交到哪里
  • method 是 form标签提交数据的方式 (GET默认 / POST / …)
  • enctype 是 form标签提交的标签夹着的那些表单值的类型 (默认是application/x-www-form-urlencoded)
  • target 是 form标签提交是在当前网页 / 新开一个标签页

使用一下form标签的提交方式

  • 表单提交GET方式 - 带参数
  • 表单提交POST方式 - 带参数
  • 表单提交POST方式 - 参数+文件


<h2>表单提交 - get方式h2>
<form action="URL" target="_blank">
    <input type="text" name="appkey" placeholder="用户appkey">
    <input type="submit" value="点击获取书籍信息"> 
form>


<h2>表单提交 - post方式(字符串内容)h2>
<form action="URL" method="POST" target="_blank">
    <input type="text" name="bookname" placeholder="书名">
    <input type="text" name="author" placeholder="作者">
    <input type="text" name="publisher" placeholder="出版社">
    <input type="text" name="appkey" placeholder="用户appkey">
    <input type="submit" value="新增一本书"> 
form>



<h2>表单提交 - post方式(带文件)h2>
<form action="URL" method="POST" enctype="multipart/form-data" target="_blank">
    <span>选择要上传的文件span>
    <input type="file" name="img">
    <input type="text" name="username" placeholder="用户名">
    <input type="submit" value="传文件和参数到后台"> 
form>

6.1 Ajax异步提交表单(重点)- 带文件

异步提交

使用JS的手段,实现表单数据的提交。

使用方法

  • 监听表单的提交事件
  • 阻止表单提交的默认行为
  • 收集表单各项的值
    • 可以一项一项的收集
    • 也可以使用 serializeArray 或 serialize 来收集
  • ajax提交数据到接口,从而完成数据的提交

jQuery中提供的serializeArray和serialize方法

  • 这两个方法是由jQuery封装的
  • 使用要求,表单各项必须有name属性;这两个方法是根据表单各项的name属性获取值的
  • 配合ajax使用要求:表单各项的name属性值 === 接口要求的参数
  • 这两个方法,不能收集文件域中选择的文件。也就是不能实现文件上传
  • 这两个方法,能够收集到隐藏域的值
  • 如果一个输入框的 disabled,禁用状态;不能通过这两个方法收集到值。
// 不用form默认提交, 换成Ajax提交
// (1): form标签 - submit提交事件
// (2): 按钮(button/input) - click点击事件(触发的提交行为) - 阻止点击的默认行为(就会阻止提交行为)
// 1. GET传参 - 表单
$("#formOne input[type=submit]").on("click", function (ev) {
     
    ev.preventDefault();
    $.ajax({
     
        type: "GET",
        url: "URL",
        data: {
     
            appkey: $("#appk").val()
        },
        success(res) {
     
            console.log(res);
        }
    })
})

// 2. POST传参 - 表单 - 不带文件
$("#formTwo input[type=submit]").on("click", function (ev) {
     
    ev.preventDefault();
    var s = $("#formTwo").serializeArray(); // 数组里套对象格式
    var s2 = $("#formTwo").serialize(); // 这个是字符串key=value&key=value格式
    $.ajax({
     
        type: "POST",
        url: "URL",
        data: s2,
        success(res) {
     
            console.log(res);
        }
    })
})

// 3. POST传参 - 表单 - 带文件
$("#formThree input[type=submit]").on("click", function (ev) {
     
    ev.preventDefault();
    var files = $('#theFile')[0].files; // 获取到文件类型对象
    if (files.length <= 0) {
      // 判断文件是否存在
        return alert('请选择文件后再上传!')
    }

    var fd = new FormData() // 表单数据 - 如果有文件必须用这个数据格式来传递数据
    fd.append('avatar123', files[0]);
    fd.append("username", $("#uname").val());

    $.ajax({
     
        method: 'POST',
        url: 'URL',
        data: fd,
        // 上传文件不需要吧data转换为字符串
        // 不要转成字符串key=value&key=value&key=value格式
        processData: false,
        // 防止JQ对内容类型操作, 直接二进制流方式上传(保证是multipart/form-data)
        contentType: false,
        success: function (res) {
     
            console.log(res)
        }
    })
})


// 总结:
// JQ提供方法 $("form标签").serialize() 收集标签里每个name属性的值和value的值然后返回一个字符串

7. 案例 - 评论

7.0 - 案例 - 评论 - 初始化列表

// 1.0 声明变量 - 定义获取当前页面评论数据 的方法
var nowPage = 1; // 当前要第几页数据
var allPage; // 一共几页
// 1.1 获取铺设评论列表区
function getCommentList() {
     
    // 1.2 调用接口 - 传递相应参数给后台 - 获取数据
    $.ajax({
     
        method: 'GET',
        url: `URL?page=${
       nowPage}&appkey=b7fc2560-5632-4da5-b625-58cff58c6b31`,
        success: function (res) {
     
            // 1.3 判断不是200证明报错 - 提示消息
            if (res.status !== 200) return alert(res.msg)
            // 1.4 保存当前一共有多少页
            allPage = res.allPage;

            // 1.5 先清空当前列表页面 - 重新铺设
            $('#cmt-list').empty();
            // 1.6 遍历铺设这次获取回来的数据
            $(res.data).each(function (i, item) {
     
                $('#cmt-list').append($(`
  • ${ item.id}>删除 评论时间:${ item.time} 评论人:${ item.username} ${ item.content}
  • `
    )); }) // 1.7 设置页码 $("#pageShow").html(nowPage); } }) } // 1.8 获取此页的数据 getCommentList(); // 1.9 绑定上一个按钮/下一个按钮点击事件 $("#last").on("click", function () { if (nowPage > 1) nowPage--; getCommentList() }) $("#next").on("click", function () { if (nowPage < allPage) nowPage++; getCommentList() })

    7.1 - 案例 - 评论 - 新增评论

    // 2.0 点击发布事件
    $(function () {
         
        $('#formAddCmt').submit(function (e) {
         
            e.preventDefault()
            // 2.1 获取表单上的内容形成key=value&key=value字符串
            var data = $(this).serialize()
            // 2.2 拼接我的授权码
            data += "&appkey=b7fc2560-5632-4da5-b625-58cff58c6b31";
            // 2.3 post发送数据给后台
            $.post('URL', data, function (res) {
         
                if (res.status !== 201) {
         
                    return alert('发表评论失败!' + res.msg);
                }
                // 2.4 发送成功后, 重新获取数据铺设页面
                nowPage = 1;
                getCommentList();
                // 2.5 复位表单输入框
                $('#formAddCmt')[0].reset()
            })
        })
    })
    

    7.2 - 案例 - 评论 - 删除评论

    // 3.0 事件委托 - 给所有删除绑定绑定点击事件
    $("#cmt-list").on("click", ".del", function () {
         
        // 3.1 去上面给删除标签绑定数据对应id, 点击获取评论对应唯一性的id
        var theId = $(this).attr("theid");
        // 3.2 调用删除接口 - 让后台删除这个数据
        $.ajax({
         
            method: 'GET',
            url: `URL?id=${
           theId}&appkey=b7fc2560-5632-4da5-b625-58cff58c6b31`,
            success: function (res) {
         
                // 3.3 如果不是200状态码, 代表删除失败给个提示, 阻止代码继续往下走
                if (res.status !== 200) return alert(res.msg);
                // 3.4 如果上面if进不去就走这里, 保存当前最大页码(因为当前页没数据了得自动回上一页)
                allPage = res.allPage;
                if (nowPage > allPage) nowPage = allPage;
                // 3.5 设置页码 - 重新获取数据 - 铺设当前页面
                getCommentList();
            }
        })
    })
    

    如有不足,请多指教,
    未完待续,持续更新!
    大家一起进步!

    你可能感兴趣的:(前端与移动开发学习笔记,Ajax编程,javascript,前端,chrome,ajax)