本文介绍: Ajax全称叫做异步JavaScript和XMLjQuery中的AjaxjQuery中发起Ajax请求常用的三个方法如下:发起不带参数请求发起带参数请求代码示例:2.3 $.ajax()代码示例接口概念接口请求流程接口测试工具Apipost,优点:不需要书写代码即可检验接口是否可以处理请求。利用BootStrap可轻松完成布局,以下为布局思路。(仅作参考)我们表单使用bootstrap的CSS样式,而该样式demo使用的是form表单form与Ajax不可混用,否则会出

Ajax

一、Ajax初识

Ajax的全称叫做异步JavaScript和XML

二、jQuery发起Ajax

jQuery中的Ajax

浏览器中提供的XMLHttpRequest用法比较复杂,所以jQuery进行了一些封装,提供了一系列Ajax相关函数极大的降低的Ajax的使用难度

jQuery中发起Ajax请求最常用的三个方法如下

2.1 $.get()

作用

格式

发起不带参数的请求

<script src="js/jquery.min.js"&gt;</script&gt;

<button class="btn-success btn"&gt;发送GET请求</button&gt;

<script&gt;
    //页面加载执行
    $(function () {
        //给按钮绑定点击事件
        $('.btn').on('click',function () {
            //事件触发则发送GET请求,以下链接接口测试平台用于响应返回我们的Ajax请求。
            $.get('http://www.escook.cn:3006/api/getbooks',function (response) {
                //回调函数有个形参可以接收响应信息,叫responseres都行,自定义
                console.log(response)
            })
        })
    })
</script>

<!--
控制台输出:
	{status: 200, msg: '获取图书列表成功', data: Array(6)}
	数据获取成功。
-->

如何查看是否成功发送请求,以及服务端是否成功返回数据

image-20220726195016171

发起带参数的请求

上一小节我们利用$.get()向服务端成功的发起get请求,而服务端也是返回data数组,携带参数可以实现只让服务端返回自己想要的那么一组数据,而不是全部。

$.get('http://www.escook.cn:3006/api/getbooks',{id:1},function (response) {
console.log(response)
})

2.2 $.post()

作用

格式

代码示例

//提交数据的地址
$.post('http://www.escook.cn:3006/api/addbook',
       //要提交的数据
       { bookname:'Ajax',author:'liuyu',publisher:'老刘出版社'},
       //回调函数查询请求返回信息
       function (response) {
    		console.log(response)
    		//控制台输出:{"status":201,"msg":"添加成功"}
		}
	)

查询post提交的数据

image-20220727015237522

查询请求头部信息是否请求成功): 略,与get一致。

查询请求返回信息:略。

2.3 $.ajax()

作用

  • 相比

    .

    g

    e

    t

    (

    )

    .get()与

    .get().post(),jQuery中提供的$.ajax()不局限于只能发送一种请求,允许我们对Ajax请求进行更详细配置

格式

代码示例

获取id为1的数据

<button class="btn-success btn">发送请求</button>
$(function () {
$('.btn').on('click',function () {
$.ajax({
type:'GET',
url:'http://www.escook.cn:3006/api/getbooks',
data:{id:1}
})
})
})

2.4 接口调试工具

接口的概念

  • 使用Ajax请求数据时,被请求的URL地址,就叫做数据接口,简称接口。
  • 每个接口都必须有请求方式

接口请求流程

接口测试工具Apipost,优点:不需要书写代码即可检验接口是否可以处理请求。

Apipost官网https://www.apipost.cn/

利用接口测试工具对接口发起GET请求:

image-20220727025601141

获取ID为1的数据

image-20220727025838448

发送POST请求:

image-20220727155304340

注:

三、案例图书管理系统

3.1 布局

利用BootStrap可轻松完成布局,以下为布局思路

官网https://v3.bootcss.com/

下载引入BootStrap.css与BootStrap.js即可

注:

先来看看最终效果

image-20220727191625671

(仅作参考)

在BootStrap文档中,找到组件,由于只涉及到调用接口进行增删改查,所以不需要用到导航条啊之类的,所以这里选用的是面板

image-20220727191929440

有了个大面板之后,就需要在里面书写input标签table标签了,而bootstrap全局CSS样式中,有写好的demo,我们直接复制修改即可

image-20220727192204229

这里选用样式为上图,删除自己不想要的,然后文本框相关的多复制两份即可

表格这里不过多说明文档中提供了很多table标签样式,有需要直接添加类名即可

源码

<!--面板-->
<div class="panel panel-info">
<div class="panel-heading">添加图书</div>
<div class="panel-body">
<!--面板内部搜索栏-->
<form class="form-inline">
<!--书名表单-->
<div class="form-group">
   <div class="input-group">
       <div class="input-group-addon">书名</div>
       <input type="text" class="form-control" id="bookname" placeholder="输入书名">
   </div>
</div>

<!--作者表单-->
<div class="form-group">
   <div class="input-group">
       <div class="input-group-addon">作者</div>
       <input type="text" class="form-control"  id="author"  placeholder="输入作者">
   </div>
</div>

<!--出版社表单-->
<div class="form-group">
   <div class="input-group">
       <div class="input-group-addon">出版社</div>
       <input type="text" class="form-control" id="publisher" placeholder="输入出版社">
   </div>
</div>

<!--提交-->
<button type="submit" class="btn btn-success" id="addbook">添加</button>
</form>
<!--面板内部搜索栏-->

<!--图书表格-->
<table class="table table table-striped table-bordered table-hover table-condensed">
<thead>
 <tr class="success">
        <th>ID</th>
        <th>书名</th>
        <th>作者</th>
        <th>出版社</th>
        <th>操作</th>

</thead>
<tbody>
<!--                <tr>-->
<!--                    <td>1</td>-->
<!--                    <td>1</td>-->
<!--                    <td>1</td>-->
<!--                    <td>1</td>-->
<!--                    <td>1</td>-->
<!--                </tr>-->
</tbody>
</table>
<!--图书表格-->
</div>
</div>
<!--面板-->

3.1.1 禁止form表单提交

详情请见第5.3章节,本章节主要以完成项目为主,进行“插播”

我们的表单使用bootstrap的CSS样式,而该样式demo使用的是form表单,form与Ajax不可混用,否则会出现提交数据时,无法正常提交的现象。

所以我们有两种方案

3.2 渲染页面

一、渲染图书列表

已知调用接口返回信息为:

通过回调函数的参数,我们获取服务端的响应数据,所以可以判断,当返回状态status为200时,获取key为data的值,该值为数组每个数组元素,为记录图书信息对象,有了对象,那我们就可以从中取出书名作者名等数据,随后渲染页面上。

那么问题来了,如何渲染页面上?

小测试:

<div></div>

<script>
let span = "<span>我是div下的span</span>"
$('div').html(span)
</script>

我们都知道,需要渲染的数据是table下的tbody下的tr和td标签,那我们可以将获取到的数据利用字符串拼接方式书写符合html格式字符串,随后利用append或者html方法实现最终效果

验证绑定获取图书列表标签是否可以渲染到页面

//定义函数。获取图书列表
function getList() {
    //发送get请求
    $.ajax({
        type:'GET',
        url:'http://www.escook.cn:3006/api/getbooks',
        //回调函数
        success:function (res) {
            //后端返回的数据中,status表示状态码,当GET请求失败时候发出弹框
            if (res.status !== 200) {
                return alert('图书列表获取失败')
            }
            //因为每次刷新添加删除都需要调用该函数渲染
            //所以在每次渲染之前,先把之前的数据删除掉。
            $('tbody').empty()
            
            //创建一个数组,随后把每一个图书数据对象取出数据,最后利用字符串拼接的方式,
            //将数据拼接html格式字符串,把每个图书的字符添加到列表中
            let rows = []
            //res.data数组对象的形式存储了数据,each遍历可以拿到每个图书对象
            $.each(res.data,function (i,item) {
                // i为对象在列表中索引item为图书对象
                rows.push('<tr><td>'+item.id+'</td><td>'+ item.bookname +'</td><td>'+ item.author +'</td><td>'+ item.publisher +'</td><td><a class="btn btn-danger" data-id='+item.id+'>删除</a></td></tr>')
                //这里的删除标签添加自定义属性data-id,值为书籍的ID,后续可用来删除,其中类btn和btn-dangerbootstrap样式
                
            })
			//join列表转字符串,随后插入tbody中,完成渲染。
            $('tbody').html(rows.join(''))
        }
    })
}

//调用函数,将数据渲染到页面上
getList()

最终效果
image-20220729205148677

3.2 实现删除功能

注意事项

代码:

//委托给a标签,删除按钮,删除按钮的类为btn-danger
$('tbody').on('click','.btn-danger',function () {
//利用attr获取触发事件对象自定义属性data-id
let delId = $(this).attr('data-id')
//调用api
$.ajax({
type:'GET',
url:"http://www.escook.cn:3006/api/delbook",
//根据接口文档传入想要删除书籍的ID
data:{id:delId},
//回调函数
success:function (res) {
if (res.status !== 200) return alert('删除失败,请重试!')
//重新渲染
getList()
}
})
})

3.4 实现添加功能

思路

  • 先获取input框输入的数据,随后将数据以post请求的方式提交到后端

API接口测试:
image-20220730205942040

代码:

//添加图书
$('#addbook').on('click',function () {
    //获取input框中的数据,并去掉首尾空格
    let bookName = $('#bookname').val().trim()
    let bookAuthor = $('#author').val().trim()
    let bookPublisher = $('#publisher').val().trim()

    //判断是否为空,只有三个框内有一个没有数据,则不往下执行
    if (bookName.length == 0 || bookAuthor.length == 0 || bookPublisher.length == 0) {
        return alert('请将表单填写完整')
    }
    //POST请求
    $.ajax({
        type:'POST',
        url:'http://www.escook.cn:3006/api/addbook',
        data: {bookname:bookName,author:bookAuthor,publisher:bookPublisher},
        success:function (response) {
            //正确响应状态码为201
            if (response.status !== 201) {
                return alert('添加失败,请重试!')
            }
            //提交成功后,重新渲染下数据
            getList()
            //把input表单的内容清空
            $('#iptbookname').val('')
            $('#iptauthor').val('')
            $('#iptpublisher').val('')
        }
    })


})

四、案例聊天机器人

'''
	本章节只提供接口地址以及使用说明源码暂无。
'''

机器人接口

接口地址http://www.liulongbin.top:3006/api/robot

image-20220810154323459

机器人语音接口

接口地址http://www.liulongbin.top:3006/api/synthesize

image-20220810154925451

五、form表单

什么是表单:

表单的组成部分

5.1 form标签的属性

5.1.1 action属性

<form>标签的属性

一、action

注意

示例

当不指定action

<form action="">
用户名<input type="text" name="iptUname">
密码<input type="password" name="iptUpassword">
<button type="submit">提交</button>
</form>

指定action时

<!--提交到Login页面-->
<form action="/login">
	......略
</form>

5.1.2 target属性

<form>标签的属性

二、target

当我们修改了action值之后,由于默认提交就会跳转到action值这个页面,并且是直接在该页面跳转,如果不想覆盖掉现在的网页,那么可以添加target属性,值为_blank,这样会另外开设标签页。

5.1.3 method属性

<form>标签的属性

三、method

get方式适合用来提交少量的、简单的数据。

post方式适合用来提交大量的、复杂的、或者包含文件上传的数据。相对来说post会比get安全一点。

在实际开发中,form表单的post提交方式用的最多,很少用get,例如登陆注册、添加数据等表单操作,都需要使用post方式来提交表单。

5.1.4 enctype属性

<form>标签的属性

四、enctype

简单来说就是:

5.2 表单的同步提交

什么是表单的同步提交:

表单同步提交的缺点:

  • form表单同步提交后,整个页面会发生跳转,跳转到action URL所指向的地址,用户体验很差。
  • form表单同步提交后,页面之前的状态和数据会丢失

解决方案

5.3 通过Ajax提交表单数据

在jQuery中,可以使用下列两种方式绑定事件,利用事件绑定来监听到表单的提交事件:

//第一种
$('form').submit(function() {})
//第二种
$('form').on('submit',function() {})

只是监听到了提交事件,但并不能阻止表单的默认行为,也就是页面跳转不能阻止,如果让它跳转了,那么页面之前的状态和数据还是丢失

阻止表单默认提交行为

监听到表单的提交事件以后,可以调用事件对象的 e.preventDefault() 函数,来阻止表单的提交和页面的跳转,示例代码如下

$('form').on('submit',function(e) {
e.preventDefault()
})

此时刷新页面将不再跳转,数据也仍然会保留在页面上。

5.4 serialize函数

作用

格式:

注意

  • 在使用serialize()函数快速获取表单数据时,必须为每个表单添加name属性

代码示例:

<form action="">
    用户名<input type="text" name="iptUname">
    密码<input type="password" name="iptUpassword">
    <button type="submit">提交</button>
</form>
$('form').on('submit',function(e) {
    e.preventDefault()

    let data = $('form').serialize()  //获取表单的数据
    console.log(data)
})

六、模板引擎

案例中渲染UI结构遇到的问题:

$.each(res.data,function (i,item) {
    rows.push('<tr><td>'+item.id+'</td><td>'+ item.bookname +'</td><td>'+ item.author +'</td><td>'+ item.publisher +'</td><td><a class="btn btn-danger" data-id='+item.id+'>删除</a></td></tr>')
})

$('tbody').html(rows.join(''))

上述代码是通过字符串拼接的形式,来渲染UI结构的。

弊端:

什么是模板引擎

模板引擎的好处:

6.1 arttemplate模板引擎

简介

安装arttemplate

一步进入安装页面

http://aui.github.io/art-template/zh-cn/docs/installation.html

第二步找到下载template-web.js

6.2 如何使用模板引擎

如何使用

代码示例:

第一步,导入模板引擎

<!--导入模板引擎-->
<script src="js/template-web.js"></script>
<!--导入之后,会在全局多出一个函数,叫做template('模板的ID','需要渲染的数据对象')-->

第二步定义数据

//在数组定义两个学生信息对象
let stuMsg = [{
'id':'1',
'name':'liuyu',
'age':22,
'school':'中国地质大学(北京)',
'college':'信息工程学院',
},{
'id':'2',
'name':'夏之悦',
'age':22,
'school':'北京大学',
'college':'光华管理学院',
}]

第三步,定义模板

<!--
第一:
	script标签默认的type是text/JavaScript,意为当前标签下的代码当做JS代码处理
而我们要写的模板,而不是js代码,所以这里需要改为text/html。
第二:
	因为第四步需要调用template函数,而该函数需要传入模板的ID,故创建ID,值为stuMsgTemplate学生信息模板。
-->
<script type="text/html" id="stuMsgTemplate">
<li>{{name}}</li>
<li>{{age}}</li>
<li>{{school}}</li>
<li>{{college}}</li>
<br>
</script>

第四步,调用template函数

//调用template,传入绑定的模板,以及模板要使用的数据,
//调用之后,会将模板内的{{}}占位符进行替换替换对应的数据,并返回替换之后的HTML代码,不过格式是str
let stuHtmlStr1 = template('stuMsgTemplate',stuMsg[0])
console.log(stuHtmlStr1)

let stuHtmlStr2 = template('stuMsgTemplate',stuMsg[1])
console.log(stuHtmlStr2)

/*控制输出:
<li>liuyu</li>
<li>22</li>
<li>中国地质大学(北京)</li>
<li>信息工程学院</li>
<br>
<li>夏之悦</li>
<li>22</li>
<li>北京大学</li>
<li>光华管理学院</li>
<br>
*/

第五步,渲染HTML

<div>学生信息表</div>
//获取到HTMLstr之后,插入到div标签下,完成渲染。
$('div').append(stuHtmlStr1).append(stuHtmlStr2)

优点:

  • 创建HTML模板之后,可以反复调用template方法生成HTML代码,随后插入到需要的地方。
  • 不需要再利用字符串拼接,这种复杂的方法。

6.3 arttemplate标准语法

什么是标准语法

6.3.1 标准输出

标准语法-输出

{{ value }}
{{ obj.key }}
{{ obj['key'] }}
{{ arr[index] }}
{{ a ? b : c }}
{{ a || b }}
{{ a + b }}

在{{}}语法中,可以进行变量的输出、对象属性的输出、三元表达式输出、逻辑输出、加减乘除等表达式输出。

6.3.2 原文输出

标准语法-原文输出

{{ @ value }}

作用

6.3.3 条件输出

标准语法-条件输出

{{if value}} 按需输出的内容 {{/if}}
//或
{{if value}} 按需输出的内容 {{else if value2}} 按需输出的内容 {{/if}}

作用

  • 如果要实现条件输出,那么可以在{{}}中使用 if…elseif…/if 的方式,进行按需输出。

代码示例:

<script src="js/template-web.js"></script>
<div>学生信息表</div>
<script type="text/html" id="stuMsgTemplate">
    <li>{{name}}</li>
    <li>{{age}}</li>
    <li>{{school}}</li>
    <li>{{college}}</li>
    <li>
        {{if isGraduate === 1}}
        已毕业
        {{else if isGraduate ===0}}
        在读
        {{/if}}
    </li>
    <br>
</script>
<script>
    //定义两个学生信息对象
    let stuMsg = [{
        'id':'1',
        'name':'liuyu',
        'age':22,
        'school':'中国地质大学(北京)',
        'college':'信息工程学院',
        'isGraduate':1,  
    },{
        'id':'2',
        'name':'夏之悦',
        'age':22,
        'school':'北京大学',
        'college':'光华管理学院',
        'isGraduate':0,
    }]
    //调用template
    let stuHtmlStr1 = template('stuMsgTemplate',stuMsg[0])
    let stuHtmlStr2 = template('stuMsgTemplate',stuMsg[1])
    $('div').append(stuHtmlStr1).append(stuHtmlStr2)
</script>

最终效果

image-20220811025810545

6.3.4 循环输出

标准语法-循环输出

{{ each arr }}
	{{ $index }} {{ $value }}
{{ /each }}

作用

代码示例:(代码以上一章节为例,为节省篇幅,只展示修改的地方)

<script type="text/html" id="stuMsgTemplate">
    <li>姓名:{{name}}</li>
    <li>年龄{{age}}</li>
    <li>学校:{{school}}</li>
    <li>学院{{college}}</li>
    <li>是否在读:
        {{if isGraduate === 1}}
        已毕业
        {{else if isGraduate ===0}}
        在读
        {{/if}}
    </li>
    <li>爱好:
        {{ each hobby }}
            {{$value}}
        {{/each}}
    </li>
    <br>
</script>
let stuMsg = [{
    'id':'1',
    'name':'liuyu',
    'age':22,
    'school':'中国地质大学(北京)',
    'college':'信息工程学院',
    'isGraduate':1,
    'hobby':['吃饭','睡觉','打游戏'],
},{
    'id':'2',
    'name':'夏之悦',
    'age':22,
    'school':'北京大学',
    'college':'光华管理学院',
    'isGraduate':0,
    'hobby':['吃饭','美妆','刷抖音'],
}]

最终效果

image-20220811031253674

6.3.5 过滤器

过滤器就好比是净水器:

自来水 --->  净水器  --->  纯净水
需要处理的值  --参数-->  过滤器函数  ---返回值-->  输出新值 

过滤器本质,就是一个function函数

格式:

代码示例:

需求:页面上显示当前时间

一、第一步

二、第二步

  • 因为模板的格式为:

    {{ value | 过滤器函数名 }}
    

    所以就有了:

    <script type="text/html" id="tplDate">
        <span>{{ currentDate | dateFormat }}</span>
    </script>
    

    这里currentDate为数据对象的key(Date对象),dateFormat为过滤器函数的函数名。

  • 定义过滤器函数

    注意!!!! 一定要写在定义数据的上面!!!

    //形参date接收模板第一次收到的数据(未经处理过的)
    template.defaults.imports.dateFormat = function(date) {
        let y = date.getFullYear()
        let m = date.getMonth() + 1
        let d = date.getDate()
        return y+'-'+m+'-'+d    //必须有return,将值返回给currentDate
    }
    
  • 最终浏览器页面为:

    '''
    浏览器页面内容:   当前时间: 2022-8-12
    '''
    

6.4 模板引擎实现原理

模板引擎的实现原理其实就是利用了正则表达式

正则与字符串操作

函数名:

作用

格式:

代码示例:

let str = 'hello'
let reg = /o/
console.log(reg.exec(str))
	// ['o', index: 4, input: 'hello', groups: undefined] 

分组

正则表达式中,()小括号包起来的内容表示一个分组,可以通过分组提取自己想要的内容,代码示例如下:

let str = '<div>我叫{{name}}}</div>'
// +表示匹配前面的子表达式一次多次
let reg = /{{([a-zA-Z]+)}}/    
let result = reg.exec(str)
console.log(result)
// ['{{name}}', 'name', index: 7, input: '<div>我叫{{name}}}</div>', groups: undefined]

可以发现

字符串的replace函数

函数名:

作用

  • 该函数为字符串内置方法,用于将一些字符替换另一些字符。

代码示例:

let str = '123456'.replace('123','ABC')
console.log(str)
	// ABC456

利用字符串替换,将正则匹配到的内容,替换成分组拿到的内容。

let str = '<div>我叫{{name}}</div>'
let reg = /{{([a-zA-Z]+)}}/    //+匹配前面的子表达式一次多次
let result = reg.exec(str)
// result = ['{{name}}', 'name', index: 7, input: '<div>我叫{{name}}}</div>', groups: undefined]
str = str.replace(result[0],result[1])
console.log(str)
	// 控制台输出:  <div>我叫name</div>

多次替换

let str = '<div>我叫{{name}},今年{{age}}岁</div>'
let reg = /{{([a-zA-Z]+)}}/    //+匹配前面子表达式一次或多次

//第一次匹配
let result = reg.exec(str)
console.log(result)  //'{{name}}', 'name', index: 7,
str = str.replace(result[0],result[1])
console.log(str)  // <div>我叫name,今年{{age}}岁</div>

//第二次匹配
let result2 = reg.exec(str)
console.log(result2)  //'{{age}}', 'age', index: 14,
str = str.replace(result2[0],result2[1])
console.log(str)  // <div>我叫name,今年age岁</div>

//第三次匹配
let result3 = reg.exec(str)
console.log(result3)  // null

多次替换(循环版):

let str = '<div>我叫{{ name }},今年{{ age }}岁</div>'
let reg = /{{s*([a-zA-Z]+)s*}}/
//+匹配前面子表达式一次或多次, s*匹配空格0次或多次。
while (reg.exec(str)) {
    let result = reg.exec(str)
    str = str.replace(result[0],result[1])
}
console.log(str)
	// 控制台输出: <div>我叫name,今年age岁</div>

有了前面的铺垫之后,接下来就是创建对象,然将对象中的值替换到str中。

let data = {'name':'liuyu','age':22}
let str = '<div>我叫{{ name }},今年{{ age }}岁</div>'
let reg = /{{s*([a-zA-Z]+)s*}}/

while (reg.exec(str)) {
    let result = reg.exec(str)
    // result[1]为通过分组获取的内容,也就是name和age
    str = str.replace(result[0],data[result[1]])
}
console.log(str)
	// 控制台输出:<div>我叫liuyu,今年22岁</div>

6.4.1 手动实现简易模板引擎

步骤:

  • 一、导入模板引擎文件

    <!--引入自定义的模板引擎文件-->
    <script src="....路径/myTemplate-web.js"></script>
    
  • 二、书写模板

    <script type="text/html" id="tpl">
    <div>我叫{{ name }},今年{{ age }}岁,来自{{ addr }}</div>
    </script>
    
  • 三、定义数据

    let data = {'name':'liuyu','age':22,'addr':'上海市徐汇区'}
    
  • 四、调用template函数

    art-template模板引擎中,我们导入template-web.js文件的同时,会在全局产生一个template函数.

    现在是自己手动实现,所以并没有该函数,接下来就是手写简易的template函数

    // template-web.js文件
    function template(id,data) {
    let str = $('#'+id).html()
    let reg = /{{s*([a-zA-Z]+)s*}}/
    while (reg.exec(str)) {
    let result = reg.exec(str)
    str = str.replace(result[0],data[result[1]])
    }
    return str
    }
    
    <!--调用-->
    <script>
    let data = {'name':'liuyu','age':22,'addr':'上海市徐汇区'}
    let htmlStr = template('tpl',data)
    console.log(htmlStr)
    // <div>我叫liuyu,今年22岁,来自上海市徐汇区</div>
    </script>
    
  • 五、渲染标签

    调用函数返回的htmlStr渲染到HTML代码结构内部即可,源码略。

七、XMLHttpRequest

什么是XMLHttpRequest:

  • XMLHttpRequest简称xhr,是浏览器提供的JavaScript对象,通过它,可以请求服务器上的数据资源,之前使用的jQuery中的Ajax函数,就是基于xhr对象封装出来的。

我们可以使用

.

g

e

t

(

)

.get()、

.get().post() 、$.ajax()发起请求,也可以直接使用xhr对象发起ajax请求。

7.1 使用xhr发起GET请求

步骤

代码示例:

//创建XHR对象
let xhr = new XMLHttpRequest()
//调用open函数,指定请求方式与URL地址
xhr.open('GET','http://www.escook.cn:3006/api/getbooks')
//调用send函数,发起Ajax请求
xhr.send()

//监听onreadystatechange事件
xhr.onreadystatechange = function () {
    //监听xhr对象的请求状态readyState;以及服务器的响应状态status
    if (xhr.readyState === 4 &amp;&amp; xhr.status === 200) {   //固定写法
        //打印服务器响应回来的数据
        console.log(xhr.responseText)
    }
}
//控制台输出;  {"status":200,"msg":"获取图书列表成功","data":[{...},{...},....]}

注意

7.1.1 xhr对象的readyState属性

XMLHttpRequest对象的readyState属性,用来表示当前Ajax请求所处的状态每个Ajax请求必须处于以下状态中的一个:

状态 描述
0 unsent xhr对象已创建,但未调用open方法
1 opened open方法已经被调用
2 headers_received send方法已经被调用,响应头也已经被接收
3 loading 数据接收中,此时response属性中已经包含部分数
4 done Ajax请求完成,这意味着数据传输已经彻底完成失败

7.1.2 发起带参数的GET请求

使用xhr对象发起带参数的GET请求时,只需要在调用xhr.open()期间,为URL地址指定参数即可:

xhr.open('get','http://www.escook.cn:3006/api/getbooks?id=1')
//控制台输出:{"status":200,"msg":"获取图书列表成功","data":[{"id":1,....}]}

URL地址中,?后面表示查询参数多个参数之间用&amp;隔开,以这种形式,可以将想要发送给服务器的数据添加到URL中,而这种形式,又叫做查询字符串

无论使用

.

a

j

a

x

(

)

还是

.ajax()、还是

.ajax()还是.get(),又或者直接使用xhr对象发起GET请求,当需要携带参数的时候本质上,都是直接将参数以查询字符串的形式,追加到URL地址的后面,发送到服务器的。

7.2 使用xhr发起POST请求

步骤

  • 创建xhr对象
  • 调用xhr.open()函数
  • 设置Content-Type属性
  • 调用xhr.send()函数,同时指定要发送的数据
  • 监听xhr.conreadystatechange事件

代码示例:

/*1.创建xhr对象*/
let xhr = new XMLHttpRequest()
/*2.调用open函数,指定请求方式以及URL*/
xhr.open('post','http://www.escook.cn:3006/api/addbook')
/*3.设置Content-Type属性(必须的操作,固定写法)*/
xhr.setRequestHeader('Content-Type','application/x-www-form-urlencoded')
/*4.调用send函数,同时将数据以查询字符串的形式,提交给服务器*/
xhr.send('bookname=刑法学讲义&amp;author=张三&amp;publisher=法内狂徒')
/*5.监听onreadystatechange事件*/
xhr.onreadystatechange = function () {
    if (xhr.readyState === 4 &amp; xhr.status === 200) {
        console.log(xhr.responseText)
    }
}
/*
控制台输出:
	{"status":201,"msg":"添加图书成功"}
*/

7.3 URL编码

现象:

  • 例如在发起带参数的GET请求时,会出现下列情况:

    //重复代码省略
    xhr.open('GET','http://www.escook.cn:3006/api/getbooks?id=1&amp;bookname=西游记')
    /*
    请求的URL地址:
     http://www.escook.cn:3006/api/getbooks?id=1&amp;bookname=%E8%A5%BF%E6%B8%B8%E8%AE%B0
    */
    

可以发现,<西游记>这三个中文汉字,变成了%E8%A5%BF%E6%B8%B8%E8%AE%B0,这种编码叫做URL编码

什么是URL编码:

URL编码的原则

  • 使用英文字符去表示非英文字符。
  • 中文编码后,三个%的内容为一个中文字符,如%E8%A5%BF = 西

7.3.1 如何对URL进行编解码

浏览器提供了URL编码与解码的API,分别是:

代码示例:

解码

let str = '%E8%A5%BF%E6%B8%B8%E8%AE%B0'
console.log(decodeURI(str))
// 西游记

编码

let str = '西游记'
console.log(encodeURI(str))
// %E8%A5%BF%E6%B8%B8%E8%AE%B0

由于浏览器会自动对URL地址进行编码操作,因为大多数情况下,程序员不需要关系URL地址的编码与解码操作。

八、数据交换格式

什么是数据交换格式:

  • 数据交换格式,就是服务端客户端之间的数据传输与交换的格式
  • 前端领域,经常提及的两种数据交换格式分别是XMLJSON,其中XML用的非常少,所以主要以JSON为主。

什么是XML

XML和HTML虽然都是标记语言,但是两者之间没有任何的关系

XML和HTML的区别

XML的缺点:

什么是JSON

作用

  • JSON是一种轻量级的文本数据交换格式,在作用上类似于XML,专门用于存储传输数据,但是JSON比XML更小、更快、更易解析

JSON格式:

练习找出不符合JSON格式的地方

let jsonStr = {
name:"liuyu",
'age':22,
"sex":'男',
"addr":undefined,
"hobby":["吃饭","睡觉",'刷抖音'],
say:function () {}
}  

8.1 序列化与反序列化

什么是序列化

序列化方法:

函数名:

代码示例:

let obj = {'name':'liuyu','age':22}
let jsonStr = JSON.stringify(obj)
console.log(jsonStr,typeof jsonStr)
//{"name":"liuyu","age":22} string

序列化方法:

函数名:

代码示例:

let jsonStr = '{"name":"liuyu","age":22}'
let obj = JSON.parse(jsonStr)
console.log(obj,typeof obj)
// {name: 'liuyu', age: 22} 'object'

九、XHR level2的新特性

旧版XMLHttpRequest的缺点

XMLHttpRequest level2的新功能

  • 可以设置HTTP请求的时限。
  • 可以使用FormData对象管理表单数据
  • 可以上传文件
  • 可以获得数据传输的进度信息

9.1 设置HTTP请求时限

有时,Ajax操作很耗时,而且无法预知要花多少时间,如果网速很慢用户可能要等很久,新版本的XMLHttpRequest对象,增加了timeout属性,可以设置HTTP请求的时限。

xhr.timeout = 3000

上面的语句,将最长等待时间设为3000毫秒,过了这个时限,就自动停止HTTP请求,与之配套的还有一个timeout事件,用来指定回调函数

xhr.ontimeout = function(event) {
alert('请求超时!')
}

代码书写位置

9.2 FormData对象管理表单数据

Ajax操作往往用来提交表单数据,为了方便表单处理,HTML5新增了一个FormData对象,可以秒你表单操作。

代码示例:

let fd = new FormData()
// 追加数据
fd.append('uname','liuyu')
fd.append('upwd','123456')

let xhr = new XMLHttpRequest()
xhr.open('post','http://www.escook.cn:3006/api/formdata')
// 新版本可以把setRequestHeader省略,因为改成默认值了。
xhr.setRequestHeader('Content-Type','application/x-www-form-urlencoded')
// 将数据提交到后端
xhr.send(fd)
xhr.onreadystatechange = function () {
if (xhr.readyState === 4 &amp; xhr.status === 200) {
// 接收服务器返回的数据,并反序列化。
console.log(JSON.parse(xhr.responseText))
}
}
/*{message: '测试FormData表单提交成功!', data: {…}}*/

实际应用中,FormData对象可以帮助我们一次性获得所有表单的数据,类似于form表单的serialize函数

<form action="" id="form1">
姓名: <input type="text">
密码<input type="text">
<button type="submit">提交</button>
</form>
let form = document.querySelector('#form1')
form.addEventListener('submit',function (e) {
e.preventDefault()
/*根据form表单创建FormData对象,会自动将表单数据填充到FormData对象中*/
let fd = new FormData(form)
let xhr = new XMLHttpRequest()
xhr.open('post','http://www.escook.cn:3006/api/formdata')
xhr.send(fd)
xhr.onreadystatechange = function () {
if (xhr.readyState === 4 &amp; xhr.status === 200) {
   console.log(JSON.parse(xhr.responseText))
}
}
})
// {message: '测试FormData表单提交成功!', data: {…}}

最终效果:

  • 表单中输入的信息,会被FormData对象所接收,后续提交到服务端,返回反序列化的数据。

9.3 上传文件

实现步骤

一、定义UI结构

<input type="file" id="file1" style="display: inline-block">
<button id="btnUpload" class="btn btn-success" style="display: inline-block">上传文件</button>
<br>
<img src="" alt="" id="img" width="400">

二、验证是否选择了文件

let btnUpload = document.querySelector('#btnUpload')
btnUpload.addEventListener('click',function () {
let files = document.querySelector('#file1').files
if (files.length <=0 ) {
return alert('请选择文件')
}
/*后续业务逻辑*/
})

三、向FormData中追加文件

//*后续业务逻辑,上述多余代码略*/
let fd = new FormData()
fd.append('avatar',files[0])
// 这里avatar后端接口的参数属性,files[0]为值,该值为选中上传的文件。

四、使用xhr发起上传文件的请求

//*后续业务逻辑,上述多余代码略*/
let fd = new FormData()
fd.append('avatar',files[0])
/*使用xhr发起上传文件的请求*/
let xhr = new XMLHttpRequest()
xhr.open('post','http://www.escook.cn:3006/api/upload/avatar')
xhr.send(fd)

五、

let btnUpload = document.querySelector('#btnUpload')
btnUpload.addEventListener('click',function () {
let files = document.querySelector('#file1').files
if (files.length <=0 ) {
return alert('请选择文件')
}
let fd = new FormData()
fd.append('avatar',files[0])

let xhr = new XMLHttpRequest()
xhr.open('post','http://www.escook.cn:3006/api/upload/avatar')
xhr.send(fd)

xhr.onreadystatechange = function () {
if (xhr.readyState === 4 & xhr.status === 200) {
   // 将返回的数据反序列
   let data = JSON.parse(xhr.responseText)
   // 判断服务器返回的状态码,在确认POST请求没问题的同时,再确认图片是否上传成功。
   if (data.status !== 200) {
       return alert('上传失败')
   }
   // 利用DOM操作,将上传到服务器的图片渲染到页面上
   let img = document.querySelector('#img')
   img.src = 'http://www.escook.cn:3006'+ data.url
}
}
})

附:服务端返回的数据

  • {message: '上传文件成功!', status: 200, url: '/uploads/1660416057298_082f06d5dbff41419db77926641cc4a9.jpg'}
    

9.4 计算文件上传进度–后续更新

十、axios – 后续更新

原文地址:https://blog.csdn.net/liuyu_719/article/details/126336555

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任

如若转载,请注明出处:http://www.7code.cn/show_48240.html

如若内容造成侵权/违法违规/事实不符,请联系代码007邮箱:suwngjj01@126.com进行投诉反馈,一经查实,立即删除!

发表回复

您的邮箱地址不会被公开。 必填项已用 * 标注