Ajax笔记
Ajax
一、Ajax初识
- 在网页中利用XMLHttpRequest对象和服务器进行数据交互的方式,就是Ajax
- Ajax可以实现网页与服务器之间的数据交互,且不需要刷新页面。
- Ajax可以在接受服务器数据的同时还可以进行页面其他操作
二、jQuery发起Ajax
浏览器中提供的XMLHttpRequest用法比较复杂,所以jQuery进行了一些封装,提供了一系列Ajax相关的函数,极大的降低的Ajax的使用难度。
2.1 $.get()
作用:
格式:
发起不带参数的请求
<script src="js/jquery.min.js"></script>
<button class="btn-success btn">发送GET请求</button>
<script>
//页面加载完执行
$(function () {
//给按钮绑定点击事件
$('.btn').on('click',function () {
//事件触发则发送GET请求,以下链接为接口测试平台,用于响应并返回我们的Ajax请求。
$.get('http://www.escook.cn:3006/api/getbooks',function (response) {
//回调函数有个形参,可以接收响应的信息,叫response、res都行,自定义。
console.log(response)
})
})
})
</script>
<!--
控制台输出:
{status: 200, msg: '获取图书列表成功', data: Array(6)}
数据获取成功。
-->
发起带参数的请求
上一小节,我们利用$.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":"添加成功"}
}
)
2.3 $.ajax()
作用:
格式:
代码示例:
<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 接口调试工具
接口的概念:
接口请求流程:
接口测试工具Apipost,优点:不需要书写代码即可检验接口是否可以处理请求。
获取ID为1的数据
发送POST请求:
注:
三、案例–图书管理系统
3.1 布局
下载并引入BootStrap.css与BootStrap.js即可
注:
(仅作参考)
在BootStrap文档中,找到组件,由于只涉及到调用接口进行增删改查,所以不需要用到导航条啊之类的,所以这里选用的是面板
有了个大面板之后,就需要在里面书写input标签和table标签了,而bootstrap的全局CSS样式中,有写好的demo,我们直接复制修改即可。
这里选用的样式为上图,删除自己不想要的,然后文本框相关的多复制两份即可。
表格这里不过多说明,文档中提供了很多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表单提交
我们的表单使用的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-danger为bootstrap样式。
})
//join列表转字符串,随后插入到tbody中,完成渲染。
$('tbody').html(rows.join(''))
}
})
}
//调用函数,将数据渲染到页面上
getList()
最终效果:
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 实现添加功能
思路:
API接口测试:
代码:
//添加图书
$('#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('')
}
})
})
四、案例–聊天机器人
'''
本章节只提供接口地址以及使用说明,源码暂无。
'''
机器人接口
五、form表单
什么是表单:
表单的组成部分
5.1 form标签的属性
5.1.1 action属性
<form>标签的属性
一、action
- action属性用来规定当提交表单时,向何处发送表单数据。
- action属性的值,应该是后端提供的一个URL地址,这个URL地址专门负责收集表单提交过来的数据。
- 当form表单在未指定action属性值的情况下,action的默认值为当前页面的URL地址。
注意:
示例:
<form action=""> 用户名:<input type="text" name="iptUname"> 密码: <input type="password" name="iptUpassword"> <button type="submit">提交</button> </form>
<!--提交到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
enctype属性用来规定在发送表单数据之前如何对数据进行编码。
它的可选值有三个,默认情况下,enctype的值为application/x-www-form-urlencoded,表示在发送前编码所有的字符。
值 描述 application/x-www-form-urlencoded 在发送前编码所有字符(默认) multipart/form-data 不对字符编码,在使用包含文件上传控件的表单时,必须使用改值 text/plain 空格转换为“+”加号,但不对特殊字符编码(很少用) 简单来说就是:
5.2 表单的同步提交
表单同步提交的缺点:
解决方案:
5.3 通过Ajax提交表单数据
在jQuery中,可以使用下列两种方式绑定事件,利用事件绑定来监听到表单的提交事件:
//第一种
$('form').submit(function() {})
//第二种
$('form').on('submit',function() {})
只是监听到了提交事件,但并不能阻止表单的默认行为,也就是页面跳转不能阻止,如果让它跳转了,那么页面之前的状态和数据还是会丢失。
阻止表单默认提交行为
当监听到表单的提交事件以后,可以调用事件对象的 e.preventDefault() 函数,来阻止表单的提交和页面的跳转,示例代码如下:
$('form').on('submit',function(e) { e.preventDefault() })
5.4 serialize函数
作用:
格式:
$('form').serialize()
注意:
代码示例:
<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)
})
六、模板引擎
$.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(''))
弊端:
-
模板引擎,它可以根据程序员指定的模板结构和数据,自动生成一个完整的HTML页面。
|---------| | '数据' |---------| |---------| | |---------| |----------| |-----|'模板引擎'|-----| 'HTML页面'| |---------| | |---------| |----------| |'模板结构' |---------| |---------|
6.1 art–template模板引擎
简介:
http://aui.github.io/art-template/zh-cn/docs/installation.html
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)
优点:
6.3 art–template标准语法
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}}
作用:
代码示例:
<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>
最终效果:
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':['吃饭','美妆','刷抖音'],
}]
最终效果:
6.3.5 过滤器
过滤器就好比是净水器:
自来水 ---> 净水器 ---> 纯净水 需要处理的值 --参数--> 过滤器函数 ---返回值--> 输出新值
格式:
-
{{ value | 过滤器函数名 }}
-
template.defaults.imports.过滤器函数名 = function(value) {/*return处理的结果*/}
与模板是配合使用的,模板通过绑定的data对象获取数据value,随后将获取到的value,丢给过滤器,过滤器的形参value接收到以后,进行一些操作之后,再return给模板得到value,最后展示在页面上的,就是最终处理好的数据。
代码示例:
一、第一步
过滤器只是在渲染数据之前,再对数据做了一遍处理操作而已。
所以我们首先要确保数据可以正常渲染。
<!--导入模板引擎--> <script src="js/template-web.js"></script>
<!--HTML代码--> <div>当前时间:</div>
<!--模板--> <script type="text/html" id="tplDate"> <span>{{ currentDate }}</span> </script>
//定义数据 let date = {currentDate:new Date()} //调用temlate let htmlStr = template('tplDate',date) //渲染到页面 $('div').append(htmlStr)
''' 浏览器页面内容: 当前时间: "2022-08-11T16:26:36.438Z" '''
二、第二步
因为模板的格式为:
{{ value | 过滤器函数名 }}
所以就有了:
<script type="text/html" id="tplDate"> <span>{{ currentDate | dateFormat }}</span> </script>
定义过滤器函数
//形参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 模板引擎实现原理
正则与字符串操作
函数名:
- exec()
作用:
格式:
代码示例:
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函数
函数名:
- 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>
-
五、渲染标签
七、XMLHttpRequest
什么是XMLHttpRequest:
我们可以使用
.
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 && 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地址中,?后面表示查询参数,多个参数之间用&隔开,以这种形式,可以将想要发送给服务器的数据添加到URL中,而这种形式,又叫做查询字符串。
无论使用
.
a
j
a
x
(
)
、还是
.ajax()、还是
.ajax()、还是.get(),又或者直接使用xhr对象发起GET请求,当需要携带参数的时候,本质上,都是直接将参数以查询字符串的形式,追加到URL地址的后面,发送到服务器的。
7.2 使用xhr发起POST请求
步骤:
代码示例:
/*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=刑法学讲义&author=张三&publisher=法内狂徒')
/*5.监听onreadystatechange事件*/
xhr.onreadystatechange = function () {
if (xhr.readyState === 4 & xhr.status === 200) {
console.log(xhr.responseText)
}
}
/*
控制台输出:
{"status":201,"msg":"添加图书成功"}
*/
7.3 URL编码
现象:
-
//重复代码省略了 xhr.open('GET','http://www.escook.cn:3006/api/getbooks?id=1&bookname=西游记') /* 请求的URL地址: http://www.escook.cn:3006/api/getbooks?id=1&bookname=%E8%A5%BF%E6%B8%B8%E8%AE%B0 */
可以发现,<西游记>这三个中文汉字,变成了%E8%A5%BF%E6%B8%B8%E8%AE%B0,这种编码叫做URL编码。
什么是URL编码:
URL编码的原则:
7.3.1 如何对URL进行编解码
代码示例:
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地址的编码与解码操作。
八、数据交换格式
什么是数据交换格式:
什么是XML:
XML和HTML虽然都是标记语言,但是两者之间没有任何的关系。
XML和HTML的区别:
XML的缺点:
什么是JSON
- JSON的英文全称是JavaScript Object Notation,即“JavaScript对象表示法”,简单来说JSON就是JavaScript对象和数组的字符串表示法,它使用文本表示一个JS对象或数组的信息,因此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
反序列化方法:
函数名:
JSON.parse()
代码示例:
let jsonStr = '{"name":"liuyu","age":22}' let obj = JSON.parse(jsonStr) console.log(obj,typeof obj) // {name: 'liuyu', age: 22} 'object'
九、XHR level2的新特性
旧版XMLHttpRequest的缺点
- 可以设置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 & 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 & 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 } } })
附:服务端返回的数据
9.4 计算文件上传进度–后续更新
十、axios – 后续更新
原文地址:https://blog.csdn.net/liuyu_719/article/details/126336555
本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。
如若转载,请注明出处:http://www.7code.cn/show_48240.html
如若内容造成侵权/违法违规/事实不符,请联系代码007邮箱:suwngjj01@126.com进行投诉反馈,一经查实,立即删除!