title: Ajax
categories: web前端学习笔记
date: 2022-03-01 15:27:51
tags:
AJAX = 异步 JavaScript 和 XML。
AJAX 是一种用于创建快速动态网页的技术。
通过在后台与服务器进行少量数据交换,AJAX 可以使网页实现异步更新。这意味着可以在不重新加载整个网页的情况下,对网页的某部分进行更新。
传统的网页(不使用 AJAX)如果需要更新内容,必需重载整个网页面。
通信协议,存放该资源的服务器名称,存放位置
客户端与服务器之间的通信过程,是 请求-处理-响应三个步骤
那么如何请求数据? -->使用对象XMLHttpRequest
,简称xhr,是浏览器提供的js成员,通过xhr可以请求服务器上的数据资源。
var xhrObj = new XMLHttpRequest()
get是问服务器要资源,post是向服务器发送资源。
$.get()
函数的用法$.get(url,[data],[callback])
,其中url是必须有的,data和callback是可有可无的
参数名 | 参数类型 | 说明 |
---|---|---|
url | string | 请求的资源地址 |
data | object | 请求资源期间要携带的参数 |
callback | function | 请求成功时的回调函数 |
<button id='btn'>发起不带参数的请求button>
<script>
$(function () {
$('#btn').on('click', function () {
$.get('http://www.liulongbin.top:3006/api/getbooks', function (res) {
console.log(res)
})
})
})
打开网页后,用f12查看请求情况,切换到network栏,然后切换到xhr栏,查看。
从headers可以看到请求的连接,以及请求的方式、请求的状态。
从response可以看到无格式的请求到的内容,有格式的则在preview栏。
<button id="btn">发起带参数的get请求button>
<script>
$(function () {
$('#btn').on('click', function () {
$.get('http://www.liulongbin.top:3006/api/getbooks', { id: 1 }, function (res) {
console.log(res);
})
})
})
$.post()
函数和get相似。
$.post(url,[data],[callback])
,其中url是必须有的,data和callback是可有可无的
参数名 | 参数类型 | 说明 |
---|---|---|
url | string | 提交数据的地址 |
data | object | 要提交的数据 |
callback | function | 数据提交成功时的回调函数 |
代码ex:
<body>
<button id="btn">用post提交数据button>
<script>
$(function () {
$('#btn').on('click', function () {
$.post('http://www.liulongbin.top:3006/api/addbook',//数据提交的url地址
{ bookname: '水浒传', author: '施耐庵', publisher: '上海图书出版社' },//要提交的数据
function (res) {
console.log(res);
})
})
})
script>
body>
$.ajax()
函数$.ajax({
type: '', // 请求的方式,例如 GET 或 POST
url: '', // 请求的 URL 地址
data: { },// 这次请求要携带的数据
success: function(res) { } // 请求成功之后的回调函数
})
$.ajax({
type: 'GET', // 请求的方式
url: 'http://www.liulongbin.top:3006/api/getbooks', // 请求的 URL 地址
data: { id: 1 },// 这次请求要携带的数据
success: function(res) { // 请求成功之后的回调函数
console.log(res)
}
})
$.ajax({
type: 'post',
url: 'http://www.liulongbin.top:3006/api/addbook',//数据提交的url地址
data: { bookname: '我也不想知道', author: '司马迁', publisher: '上海图书出版社' },
success: function (res) {
console.log(res);
}
})
javascript trim()
方法可以去除掉字符串头尾的空白符,其中空白符包括空格,tab,换行符等
属性 | 值 | 描述 |
---|---|---|
action | url地址 | 规定当提交表单时,向何处发送表单数据 |
method | get或post | 规定以何种方式把表单数据提交到action URL |
enctype | application/x-www-form-urlencoded multipart/form-data text/plain | 规定在发送表单数据之前如何对其进行编码 |
target | _blank _self _parent _top framename | 规定在何处打开action URL |
action属性的值应该是由后端提供的一个url地址,这个url地址专门负责接收表单提交过来的数据。如果form表单没有指定action属性值,那么action的默认值就是当前页面的url地址。提交表单后,页面会立刻跳转到action属性指定的url地址
默认情况下,method 的值为 get
get 方式适合用来提交少量的、简单的数据。
post 方式适合用来提交大量的、复杂的、或包含文件上传的数据。
在实际开发中, 表单的 post 提交方式用的最多,很少用 get。例如登录、注册、添加数据等表单操作,都需要使用 post 方式来提交表单。
值 | 属性 |
---|---|
application/x-www-form-urlencoded | 在发送前编码所有字符(默认) |
| multipart/form-data | 不对字符编码。
在使用包含文件上传控件的表单时,必须使用该值。 |
| text/plain | 空格转换为 “+” 加号,但不对特殊字符编码。(很少用) |
不上传文件就直接不写这个属性就行
表单同步提交是指点击submit按钮后,页面会直接跳转到action URL。
缺点是导致用户体验感差、页面之前的状态和数据都会丢失
解决方法:表单只负责采集数据,ajax负责将数据提交到服务器
$('#form1').submit(function(e) {
alert('监听到了表单的提交事件')
})
$('#form1').on('submit', function(e) {
alert('监听到了表单的提交事件')
})
$('#form1').submit(function(e) {
// 阻止表单的提交和页面的跳转
e.preventDefault()
})
$('#form1').on('submit', function(e) {
// 阻止表单的提交和页面的跳转
e.preventDefault()
})
serialize()函数
$(selector).serialize()
serialize()函数可以一次性获得表单中的所有数据
<form id="form1">
<input type="text" name="username" />
<input type="password" name="password" />
<button type="submit">提交button>
form>
$('#form1').serialize()
// 调用的结果:
// username=用户名的值&password=密码的值
注意:在使用 serialize() 函数快速获取表单数据时,必须为每个表单元素添加 name 属性。
jquery对象转化为原生dom对象->使用 jquery对象[0]
当我们想要把某个ui结构渲染到页面上时,一般情况下会采用字符串拼接的方式。但是如果ui结构比较复杂,此时对于单引号的使用就要格外注意,而且需求一旦发生变化,修改起来也十分困难。由此我们引入了模板引擎来解决这一问题。
var rows = []
$.each(res.data, function (i, item) { // 循环拼接字符串
rows.push('' + item.content +'评论时间:'+ item.time +'评论人:'+ item.username +'')
})
$('#cmt-list').empty().append(rows.join('')) // 渲染列表的UI结构
模板引擎可以根据我们指定的模板结构和数据自动生成一个完整的html页面
1.导入模板引擎
导入后,在windows全局,则多了一个函数,叫做template("模板的id",需要渲染的数据对象)
<script src="./lib/template-web.js">script>
2.定义需要渲染的数据
var data = { name: 'zs' ,age:20}
3.定义模板
<script type="text/html" id="tpl-user">
<h1>{{name}} ------ {{age}}</h1>
script>
4.调用template函数
var htmlStr = template('tpl-user', data)
5.渲染html结构
$('#container').html(htmlStr)
全部代码:
<head>
<script src="./lib/template-web.js">script>
<script src="./lib/jquery.js">script>
head>
<body>
<div id="container">div>
<script type="text/html" id="tpl-user">
<h1>{{name}} ------ {{age}}</h1>
script>
<script>
// 2. 定义需要渲染的数据
var data = { name: 'zs', age: 20, test: '测试原文输出
', flag: 1, hobby: ['吃饭', '睡觉', '写代码'], regTime: new Date() }
// 4. 调用 template 函数
var htmlStr = template('tpl-user', data)
console.log(htmlStr)
// 5. 渲染HTML结构
$('#container').html(htmlStr)
script>
body>
{{value}}//变量的输出
{{obj.key}}//对象属性
{{obj['key']}}
{{a ? b : c}}//三元表达式
{{a || b}}//逻辑
{{a + b}}//加减乘除等表达式
{{@ value }}
如果要输出的 value 值中,包含了 HTML 标签结构,则需要使用原文输出语法,才能保证 HTML 标签被正常渲染
{{if value}} 按需输出的内容 {{/if}}
{{if v1}} 按需输出的内容 {{else if v2}} 按需输出的内容 {{/if}}
{{each arr}}
{{$index}} {{$value}}
{{/each}}
{{value | filterName}}
定义过滤器的基本语法:
template.defaults.imports.filterName = function(value){
// return处理的结果
}
ex:格式化时间过滤器
<div id="container">div>
<script type="text/html" id="tpl-user">
<h3>{{regTime | dateFormat}}</h3>
script>
<script>
template.defaults.imports.dateFormat = function (date) {
var y = date.getFullYear()
var m = date.getMonth() + 1
var d = date.getDate()
return y + '-' + m + '-' + d
}
var data = { regTime: new Date() }
var html = template('tpl-user', data)
$('#container').html(html)
script>
exec函数用于检索字符串中的正则表达式的匹配,如果字符串中有匹配的值,则返回一个数组,其中存储匹配的结果,否则返回null
RegExpObject.exec(string)
下面以此例来解释exec函数返回的数组的内容
var str = 'hello'
var pattern = /o/
console.log(pattern.exec(str))
- 0: “o” 与正则表达式相匹配的文本
- groups: undefined 存储着所有的命名捕获组。
- index: 4 index 属性声明的是匹配文本的第一个字符的位置
- input: “hello” 存放的是被检索的字符串 string
- length: 1 数组长度
//创建xhr对象
var xhr = new XMLHttpRequest()
//调用open函数,指定请求方式与url地址
xhr.open('get', 'http://www.liulongbin.top:3006/api/getbooks?publisher=北京图书出版社')//?后面是带的参数 这种在 URL 地址后面拼接的参数,叫做查询字符串。
//调用send函数,发起ajax请求
xhr.send()
//监听
xhr.onreadystatechange = function () {
// 监听 xhr 对象的请求状态 readyState ;与服务器响应的状态 status
if (xhr.readyState === 4 && xhr.status === 200) {
console.log(xhr.responseText);
console.log(typeof xhr.responseText);
console.log(JSON.parse(xhr.responseText));//将json字符串转换成JavaScript对象
}
}
readyState属性
值 | 状态 | 描述 |
---|---|---|
0 | unsent | XmlHttpRequest对象已被创建,但尚未调用open方法 |
1 | opened | open方法已经被调用 |
2 | headers_received | send方法已经被调用 |
3 | loading | 数据接收中,此时 response 属性中已经包含部分数据。 |
4 | done | Ajax 请求完成,这意味着数据传输已经彻底完成或失败。 |
url地址中不允许出现中文字符,如果url中需要包含中文字符,那么必须对其进行编码。
浏览器提供了 URL 编码与解码的 API,分别是:
encodeURI() 编码的函数
decodeURI() 解码的函数
// 1. 创建 xhr 对象
var xhr = new XMLHttpRequest()
// 2. 调用 open()
xhr.open('POST', 'http://www.liulongbin.top: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)
}
}
新功能
xhr.timeout = 3000//设置http请求的时限为3000毫秒
xhr.ontimeout = function(event){
alert('请求超时!')
}
// 1. 新建 FormData 对象
var fd = new FormData()
// 2. 为 FormData 添加表单项
fd.append('uname', 'zs')
fd.append('upwd', '123456')
// 3. 创建 XHR 对象
var xhr = new XMLHttpRequest()
// 4. 指定请求类型与URL地址
xhr.open('POST', 'http://www.liulongbin.top:3006/api/formdata')
// 5. 直接提交 FormData 对象,这与提交网页表单的效果,完全一样
xhr.send(fd)
xhr.onreadystatechange = function () {
if (xhr.readyState === 4 && xhr.status === 200) {
console.log(JSON.parse(xhr.responseText));
}
}
获取表单元素:
var form = document.querySelector('#form1')
form.addEventListener('submit', function (e) {
e.preventDefault()//阻止默认提交行为
// 创建formdata,快速获得表单中的数据
var fd = new FormData(form)
var xhr = new XMLHttpRequest()
xhr.open('post', 'http://www.liulongbin.top:3006/api/formdata')
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));
}
}
})
实现步骤
var btnUpload = document.querySelector('#btnUpload')
btnUpload.addEventListener('click', function () {
//获取到选择的列表
var files = document.querySelector('#file1').files
if (files.length <= 0)
return alert('请选择要上传的文件!')
var fd = new FormData()
fd.append('avatar', files[0])
// 1. 创建 xhr 对象
var xhr = new XMLHttpRequest()
// 显示文件的上传进度
xhr.upload.onprogress = function (e) {
if (e.lengthComputable) {
var percentComplete = Math.ceil((e.loaded / e.total) * 100)
console.log(percentComplete)
$('#percent').attr('style', 'width:' + percentComplete + '%')
// 3. 显示当前的上传进度百分比
.html(percentComplete + '%')
}
}
//进度条完成以后设置样式
xhr.upload.onload = function () {
$('#percent')
// 移除上传中的类样式
.removeClass()
// 添加上传完成的类样式
.addClass('progress-bar progress-bar-success')
}
// 2. 调用 open 函数,指定请求类型与URL地址。其中,请求类型必须为 POST
xhr.open('POST', 'http://www.liulongbin.top:3006/api/upload/avatar')
// 3. 发起请求
xhr.send(fd)
xhr.onreadystatechange = function () {
if (xhr.readyState === 4 && xhr.status === 200) {
var data = JSON.parse(xhr.responseText)
if (data.status === 200) { // 上传文件成功
// 将服务器返回的图片地址,设置为 标签的 src 属性
document.querySelector('#img').src = 'http://www.liulongbin.top:3006' + data.url
} else { // 上传文件失败
console.log(data.message)
}
}
}
})
概念:axios是专注网络数据请求的库,相比于XHR对象,axios简单易用
axios.get('url', { params: { /*参数*/ } }).then(callback)
ex:
// 请求的 URL 地址
var url = 'http://www.liulongbin.top:3006/api/get'
// 请求的参数对象
var paramsObj = { name: 'zs', age: 20 }
// 调用 axios.get() 发起 GET 请求
axios.get(url, { params: paramsObj }).then(function(res) {
// res.data 是服务器返回的数据
var result = res.data
console.log(res)
})
axios.post('url', { /*参数*/ }).then(callback)
ex:
// 请求的 URL 地址
var url = 'http://www.liulongbin.top:3006/api/post'
// 要提交到服务器的数据
var dataObj = { location: '北京', address: '顺义' }
// 调用 axios.post() 发起 POST 请求
axios.post(url, dataObj).then(function(res) {
// res.data 是服务器返回的数据
var result = res.data
console.log(result)
})
//get
axios({
method: 'GET',
url: 'http://www.liulongbin.top:3006/api/get',
params: { // GET 参数要通过 params 属性提供
name: 'zs',
age: 20
}
}).then(function(res) {
console.log(res.data)
})
axios({
method: 'POST',
url: 'http://www.liulongbin.top:3006/api/post',
data: { // POST 数据要通过 data 属性提供
bookname: '程序员的自我修养',
price: 666
}
}).then(function(res) {
console.log(res.data)
})
概念:JSON 的英文全称是 JavaScript Object Notation,即“JavaScript 对象表示法”。简单来讲,JSON 就是 Javascript 对象和数组的字符串表示法,它使用文本表示一个 JS 对象或数组的信息,因此,JSON 的本质是字符串。
{key:value,key:value,·····}
其中属性名必须是使用英文的双引号包裹的字符串,如果属性值也是字符串类型的,则必须也用双引号包裹
ex:
{
"name": "zs",
"age": 20,
"gender": "男",
"address": null,
"hobby": ["吃饭", "睡觉", "打豆豆"]
}
[ "java", "python", "php" ]
[ 100, 200, 300.5 ]
[ true, false, null ]
[ { "name": "zs", "age": 20}, { "name": "ls", "age": 30} ]
[ [ "苹果", "榴莲", "椰子" ], [ 4, 50, 5 ] ]
注意:
json用于在计算机与网络之间存储和传输数据
json的本质是用字符串来表达JavaScript对象/数组数据
json转js ->JSON.parse() 又称为json反序列化
js转json ->JSON.stringify() 又称为json序列化
同源: 如果两个页面的协议、域名、端口都相同,则称两个页面具有相同的源
同源策略是浏览器提供的一个安全功能,它规定A网站的JavaScript不允许和非同源的网站B之间 进行交互。
- 无法读取非同源网页的 Cookie、LocalStorage 和 IndexedDB
- 无法接触非同源网页的 DOM
- 无法向非同源地址发送 Ajax 请求
浏览器允许发起跨域请求,但是,跨域请求回来的数据,会被浏览器拦截,无法被页面获取到
那么如何实现跨域请求?有两种解决方案,JSONP和CORS
JSONP:出现的早,兼容性好(兼容低版本IE)。是前端程序员为了解决跨域问题,被迫想出来的一种临时解决方案。缺点是只支持 GET 请求,不支持 POST 请求。
CORS:出现的较晚,它是 W3C 标准,属于跨域 Ajax 请求的根本解决方案。支持 GET 和 POST 请求。缺点是不兼容某些低版本的浏览器。
JSONP是JSON的一种使用方式,可用通过来解决主流浏览器的跨域数据访问问题
实现原理:
因为浏览器受同源策略的影响,网页无法通过ajax请求非同源的接口数据。但是script标签不受浏览器同源策略影响,因此可以通过src属性,来请求非同源的js脚本。
所以JSONP就是利用这个src属性,来请求跨域的数据接口,共通过函数调用的形式,接收跨域接口响应回来的数据
缺点:jsonp只支持get请求,不支持post请求
jsonp和ajax之间没有任何关系,不能把jsonp请求数据的方式叫做Ajax。因为jsonp并没有使用xhr对象
$.ajax({
url: 'http://ajax.frontend.itheima.net:3006/api/jsonp?name=zs&age=20',
// 如果要使用 $.ajax() 发起 JSONP 请求,必须指定 datatype 为 jsonp
dataType: 'jsonp',
success: function(res) {
console.log(res)
}
})
默认情况下,使用 jQuery 发起 JSONP 请求,会自动携带一个callback=jQueryxxx 的参数,jQueryxxx 是随机生成的一个回调函数名称。
jsonp的参数和回调函数的名称是可以自定义的
$.ajax({
url: 'http://ajax.frontend.itheima.net:3006/api/jsonp?name=zs&age=20',
dataType: 'jsonp',
// 发送到服务端的参数名称,默认值为 callback
jsonp: 'callback',
// 自定义的回调函数名称,默认值为 jQueryxxx 格式
jsonpCallback: 'abc',
success: function(res) {
console.log(res)
}
})
jQuery 中的 JSONP,也是通过
标签的 src 属性实现跨域数据访问的,只不过,jQuery 采用的是动态创建和移除
标签的方式,来发起 JSONP 数据请求。
在发起 JSONP 请求的时候,动态向中 append 一个
标签;
在 JSONP 请求成功以后,动态从中移除刚才 append 进去的
标签;
<body>
<div class="container">
<img src="./images/taobao_logo.png" alt="" class="logo" />
<div class="box">
<div class="tabs">
<div class="tab-active">宝贝div>
<div>店铺div>
div>
<div class="search-box">
<input type="text" class="ipt" placeholder="请输入要搜索的内容" id="ipt" /><button class="btnSearch">
搜索
button>
div>
<div id="suggest-list">div>
div>
div>
<script type="text/html" id="tpl-suggestList">
{{each result}}
<div class="suggest-item">{{$value[0]}}</div>
{{/each}}
script>
<script>
// 防抖
var timer = null//定义延时器
var catchobj = {}//全局缓存对象
function debance(keywords) {
timer = setTimeout(() => {
getSuggestList(keywords)
}, 300);
}
//获取用户输入的搜索关键词
$('#ipt').on('keyup', function () {
clearTimeout(timer)
var keywords = $(this).val().trim()
//搜索关键词为空时隐藏搜索建议列表
if (keywords.length <= 0)
return $('#suggest-list').empty().hide()
//先判断缓存中是否有数据
if (catchobj[keywords]) {
return renderSuggestList(catchobj[keywords])
}
// getSuggestList(keywords)
debance(keywords)
})
//获取搜索建议列表
function getSuggestList(kw) {
$.ajax({
url: "https://suggest.taobao.com/sug?q=" + kw,
dataType: "jsonp",
success: function (response) {
renderSuggestList(response);
}
});
}
// 渲染ui结构
function renderSuggestList(res) {
if (res.result.length <= 0)
return $('#suggest-list').empty().hide()
var htmlstr = template('tpl-suggestList', res)
$('#suggest-list').html(htmlstr).show()
//获取用户输入的内容当作键
var k = $('#ipt').val().trim()
catchobj[k] = res
}
script>
body>
请求头部用于描述客户端的基本信息,从而把这些信息告诉服务器。
头部字段 | 说明 |
---|---|
Host | 要请求的服务器域名 |
Connection | 客户端与服务器的连接方式(close 或 keep-alive) |
Conten-Length | 用来描述请求体的大小 |
Accept | 客户端能接收什么类型的返回内容 |
User-Agent | 产生请求的浏览器类型 |
Content-type | 客户端告诉服务器实际发送的数据类型 |
Accept-Encoding | 客户端可接收的内容压缩编码形式 |
Accept-Language | 用户期望接收哪种人类语言的文本内容 |
请求体中存放的,是要通过 POST 方式提交到服务器的数据。
注意:只有 POST 请求才有请求体,GET 请求没有请求体!
状态行由 http协议版本,状态码,状态码的描述文本三部分组成
方法 | 描述 |
---|---|
GET | (查询)发送请求来获得服务器上的资源,请求体中不会包含请求数据,请求数据放在协议头中 |
POST | (新增)向服务器提交资源(例如提交表单或上传文件)。数据被包含在请求体中提交给服务器 |
PUT | (修改)向服务器提交资源,并使用提交的新资源,替换掉服务器对应的旧资源 |
DELETE | (删除)请求服务器删除指定的资源 |
HEAD | (新增)向服务器提交资源(例如提交表单或上传文件)。数据被包含在请求体中提交给服务器 |
OPTIONS | 获取http服务器支持的http请求方法,允许客户端查看服务器的性能,比如ajax跨域时的预检等 |
CONNECT | 建立一个到由目标资源标识的服务器的隧道 |
TRACE | 沿着到目标资源的路径执行一个消息环回测试,主要用于测试或诊断 |
PATCH | 是对 PUT 方法的补充,用来对已知资源进行局部更新 |
https://developer.mozilla.org/zh-CN/docs/Web/HTTP/Status
状态码由三位数组成,第一位数决定了状态码的类型
分类 | 分类描述 |
---|---|
1** | 信息,服务器收到请求,需要请求者继续执行操作 |
2** | 成功,操作被成功接受并处理 |
3** | 重定向,需要进一步的操作以完成请求 |
4** | 客户端错误 ,请求包含语义错误或无法完成请求 |
5** | 服务器错误,服务器在处理请求的过程中发生了错误 |