AJXS学习
一.初识AJXS
1.浏览器和服务器
浏览器访问的资源存放在服务器上。
浏览器负责浏览资源,服务器负责提供资源
2.url网址
url网址的作用:标记某个资源,在网络中的唯一地址,只有通过url地址,才能定位资源的存放位置,从而成功访问到对应的资源。
url网址组成:
http(协议)😕/www.itcast.cn(主机名):80(端口号)/2018/images/logo.png(资源存放的路径)
协议:协议就是浏览器和服务器之间传输数据的规则,保证都能读懂对方发来的内容
主机名:标识服务器在互联网中的唯一地址,确保能够访问到他
端口解释:
1.端口号有效范围在0-65535之间的整数
2.标识服务器里不同服务
3.浏览器默认访问的都是80端口
路径:确定在服务器上具体位置
3.请求和响应
请求:浏览器通过网络去服务器要资源的过程
响应:服务器通过浏览器返回资源的过程
4.Ajax讲解
概念:Ajax是一种在js代码中发起一次请求并获取相应数据的技术
使用场景:
1.比如验证手机号是否在服务器已经注册过了;
2.根据输入关键字联想菜单提示数据切换;
3.根据增和删除,修改页面数据;
4.以上效果数据都在服务器上,所以浏览器刷新数据也还在
5.Ajax基础使用
Ajax是浏览器向服务器请求数据的一种技术
axios是库,对这个技术具体代码的实现
axios的使用:
1.先引入axios.js文件到自己的网页中
文件连接:https://cdn.jsdelivr.net/npm/axios/dist/axios.min.js
2.明确axios的使用语法:
axios({
url:'请求的URL地址',
method:'请求的方法'
}).then((result)=>{
//.then用来指定请求成功之后的回调函数
//形参中的result是请求成功之后的结果
})
3.请求的url地址,就是标记资源的url网址
4.请求的方法,标记本次请求的动作不同(主要浏览器端要求什么,我们就写什么,有5种固定名字的值)
POST:向服务器新增数据
GET:从服务器获取数据
DELETE:删除服务器上的数据
PUT:更新服务器上的数据(侧重于完整更新:例如更新用户的完整信息)
PATCH:更新服务器上的数据(侧重于部分更新:例如只更新用户的手机号)
5.根据服务器的数据url网址的文档说明,我们编写代码请求一次数据
6.运行后结果,在控制台可以看到,请求并接受到此url网址返回的响应结果
例子:
<!-- 目标:使用Ajax技术,在代码中获取图书列表数据
技术:axios网络请求的库
做法:
1.先引入axios.js文件,会在window下有个axios全局方法
2.根据axios语法来请求数据地址的资源 -->
<script src="https://cdn.jsdelivr.net/npm/axios/dist/axios.min.js"></script>
<script>
axios({
url: 'http://ajax-base-api-t.itheima.net/api/getbooks',
method: 'GET'
}).then((result) => {
console.log(result)
})
</script>
6.Ajax传参使用
axios({
url:'http://ajax-base-api-t.itheima.net/api/getbooks',
method:'GET',
params:{//携带查询参数
//参数名:值
id=1,
bookname:'西游记'
}
}).then((result)=>{
console.log(result)
})
//查询的参数名要和服务器端对应上,会有文档使用
传递的查询参数值要真实有效,才会返回对应的结果
7.url编码
url地址中,不允许出现中文和空格等特殊符号,所以自动转换成url编码
格式:%xx%xx%xx
js内置了2个方法,可以对字符串进行url编码和url解码
//window对象内置的方法encodeURI和decodeURI
//中文->url编码
let str="西游记"
let urlStr=encodeURI(str)
console.log(urlStr);
//url编码->中文
let zhStr=decodeURI(urlStr)
console.log(zhStr)
8.POST方法
GET和POST本质上都是http请求,区别只是被贴上了不同的请求方式,后端会根据不同的方式执行不同的代码操作,所以在url?携带参数还是请求体里携带参数,要和后端代码对上即可使用
不建议在GET上携带数据发给后端,因为浏览器对GET方式传参url长度有限制
axios({
url: 'http://ajax-base-api-t.itheima.net/api/addbook',
method: 'POST',
//params:参数值对应(query查询参数)
//data:请求体参数(body请求体)
data: {
bookname: '大学英语必修1',
author: 'aaa',
publisher: 'xx出版社'
}
}).then((result) => {
console.log(result)
})
9.请求报文
一次完整的传输过程,是一次请求对应一次响应,在传输的过程中,数据包就是报文
请求报文:规定了浏览器向服务器,以什么格式把数据发送
响应报文:规定了服务器向浏览器,以什么格式把数据返回
请求报文组成:
1.请求行:
请求方式:(GET/POST/DELETE/PUT/PATCH)
请求url:资源在服务器地址
协议版本:默认HTTP/1.1
2.请求头部:头部参数名:值
3.请求体:携带给服务器的数据
10.响应报文
响应报文组成:
1.响应行:
协议版本:默认HTTP/1.1
响应状态码:服务器返回的一个文字标识,代表本次响应的描述
响应状态描述:服务器返回的一个文字标识,代表本次响应的描述
2.响应头部:头部参数名:值
3.响应体:服务器返回的响应数据
11.响应码
1.常见的响应状态码
1XX 响应中–临时状态码,表示请求已经接受,告诉客户端应该继续请求或者如果它已经完成则忽略它
2XX 成功–表示请求已经被成功接受,处理已完成
3XX 重定向–重定向到其他地方(让客户端再发起一个请求以完成整个处理)
4XX 客户端错误–处理发生错误,责任在客户端,如:客户端的请求一个不存在的资源,客户端未被授权,禁止访问等
5XX 服务器端错误–处理发生错误,责任在服务器端,如:服务端抛出异常,路由出错,HTTP版本不支持等
200:OK 请求成功
201:Created 资源在服务器端已成功创建
302:Moved Temporarily 资源临时性重定向,响应体中不包含任何资源内容
304:Not Modified 资源在客户端被缓存(一般是css,js,图片文件)
400:Bad Request 客户端的请求方式、或请求参数有误导致的请求失败
401:Unauthorized 客户端的用户身份认证未通过,导致的此次请求失败
404:Not Found 客户端请求的资源地址错误,导致服务器无法找到资源
500:Internal Server Error 服务器内部错误,导致的本次请求失败
12.接口相关
1.接口:其实就是提供服务器的url网址,我们前面想要数据/提交数据,需要知道服务器在互联网中的唯一url地址
2.而服务器会把一些接口地址罗列整理到一个文档上
3.接口文档:就是接口使用说明书
4.接口文档格式:包含如下内容
接口名称:接口的名称,用来快速区分每个接口的作用。如:登录接口、添加图书接口
接口URL:客户端发起Ajax调用此接口时,请求的URL地址
请求方式:接口的请求方式,如:GET、POST、PUT、DELETE等
请求参数:请求此接口时,需要发送到服务器的查询参数或请求体
返回示例:当接口请求成功后,服务器响应回来的数据的基本格式
返回参数说明:接口响应结果的详细描述
13.逻辑码
位置:相应报文-响应体数据中 这次业务逻辑是否完全成功 每个数字不固定,需要和后台约定
二.表单和文件上传
1.表单
1.表单是网页里的form标签以及一些输入框和下拉菜单等等,用于手机用户输入的信息
2.表单的组成:
表单标签
表单域
表单按钮
3.表单标签指的是from标签
4.表单域:常见的有input、textarea、select等
每个表单域必须包含name属性
5.表单按钮
type的默认值就是submit
2.表单_自我提交
表单的代码
<form>
<div>
<!-- 用户名 -->
<span>用户名:</span>
<input type="text" name="username">
</div>
<div>
<!-- 密码 -->
<span>登录密码:</span>
<input type="password" name="password">
</div>
<div>
<!-- 提交按钮 -->
<button>提交</button>
</div>
</form>
2.form标签的两个属性,可以设置提交到的地址和请求的方法
action:接口的url地址,把表单采集到的数据,提交到哪个接口中
method:GET或POST,数据的提交方式(默认值为GET)
3.请求的地址和方式如下:
接口地址:http://ajax-api.itheima.net/api/data
请求方式:POST
总结:
1.form表单提交是自身特性,和Ajax没有关系
2.form表单提交,会让浏览器跳转到action指定的地址并提交数据,体验非常不好
3.Ajax+axios的提交常用,不会刷新当前页面并进行一次请求提交
3.表单_Ajax提交
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Document</title>
</head>
<body>
<form>
<div>
<!-- 用户名 -->
<span>用户名:</span>
<input type="text" name="username">
</div>
<div>
<!-- 密码 -->
<span>登录密码:</span>
<input type="password" name="password">
</div>
<div>
<!-- 提交按钮 -->
<button>提交</button>
</div>
</form>
<script src="https://cdn.jsdelivr.net/npm/axios/dist/axios.min.js"></script>
<script>
//目标:Ajax提交表单
//1.提交按钮->提交/点击事件
//提交按钮->绑定点击事件(检测它的点击动作,它会触发默认行为)
//表单标签->绑定提交事件
document.querySelector('form').addEventListener('submit', e => {
e.preventDefault()
//2.收集表单里值
let username = document.querySelector('input[name=username]').value
let password = document.querySelector('input[name=password]').value
//3.用axios提交到服务器
axios({
url: 'http://ajax-api.itheima.net/api/data',
method: 'POST',
data: {
username: username,
password: password
}
}).then(res => {
console.log(res);
})
})
</script>
</body>
</html>
4.表单_整体获取
一个一个标签获取,多的话会很麻烦,解决方案:使用form-serialize.js插件
引入js地址,然后此库的使用语法如下:
serialize(form表单的DOM对象)//返回值:name参数名=值&name参数名=值,例如:‘username=admin&password=123456’
serialize(form表单的DOM对象,{hash:true})//返回值:{name参数名:值,name参数名:值},例如:{username:'admin',password:'123456'}
5.文件上传
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Document</title>
</head>
<body>
<!-- accept设置文件选择的类型 image/*固定写法(只能选择图片文件) -->
<input type="file" id="myFile" accept="image/*">
<button>点击上传文件</button>
<script src="https://cdn.jsdelivr.net/npm/axios/dist/axios.min.js"></script>
<script>
//目标:文件上传
//详细:点击按钮,把选择的文件上传到服务器上
//1.点击事件
document.querySelector('button').addEventListener('click', e => {
//2.获取到文件
//拿到input标签对象.files,原地返回文件数组
let fileList = document.querySelector('#myFile').files
//3.把文件传递给服务器
//如果接口文档要求传递请求体(form-data内容类型)
//使用:window提供的FormData构造函数,来实例化一个表单容器对象
//语法:
/*
let fd=new FormData()
fd.append(参数名,前端要传的值)
//如果还有参数名和值继续调用append添加到fd中
*/
let fd = new FormData()
fd.append('avatar', fileList[0])
axios({
url: 'http://ajax-api.itheima.net/api/file',
method: 'POST',
data: fd
}).then(res => {
console.log(res)
})
})
</script>
</body>
</html>
6.请求体类型
1.application/x-www-form-urlencoded(key=value&key=value的字符串)
表单中不包含文件上传的场景,适用于普通数据的提交
2.multipart/form-data
表单中包含上传文件的场景
3.application/json
上传json格式数据
三.XHR和Promise
1.Ajax原生学习
axios.js是一个库,内部是原生js代码,实际它是对原生的代码进行了封装。
Ajax如果用原生js实现,需要使用window提供的一个构造函数,叫XMLHttpRequest
使用语法如下:
//1.创建一个xhr对象
let xhr = new XMLHttpRequest()
//2.设置请求方式和请求地址 xhr.open("请求方式","请求地址")
xhr.open('GET', 'http://ajax-api.itheima.net/api/province')
//3.发送请求
xhr.send()
//4.监听load(请求成功)事件==>可以获取响应数据
xhr.addEventListener('load', function () {
console.log(xhr.response)//响应体数据
//知识点:把JSON格式字符串==>转成JS数据类型
//语法:JSON.parse(JSON字符串)
//返回值:JS数据类型
let result = JSON.parse(xhr.response)
console.log(result);
})
2.Ajax原生传参
//1.创建一个xhr对象
let xhr = new XMLHttpRequest()
//2.设置请求方式和请求地址 xhr.open("请求方式","请求地址")
xhr.open('GET', 'http://ajax-api.itheima.net/api/city?pname=辽宁省')
//3.发送请求
xhr.send()
//4.监听load(请求成功)事件==>可以获取响应数据
xhr.addEventListener('load', function () {
console.log(xhr.response)//响应体数据
let result = JSON.parse(xhr.response)
console.log(result);
})
3.JSON
1.JSON是一种数据交换格式,它本质上是用字符串的方式来表示对象或数组类
2.用字符串的方式来表示的对象或数组类型的数据,叫做JSON数据
对象格式JSON字符串
key必须用双引号包起来
'{"userName":"小马","age":16,"sex":"男"}'
数组格式JSON字符串
'["小马",16,"男"]'
3.相互转换
<script>
//1.JS数据类型==>JSON字符串
//语法:JSON.stringify(JS数据类型)
//返回值:JSON字符串
let obj = {
username: '小马',
age: 16,
sex: '男'
}
console.log(JSON.stringify(obj));
//2.JSON字符串==>JS数据类型
//语法:JSON.parse(JSON字符串)
let jsonStr = '{"username":"小马","age":16,"sex":"男"}'
console.log(JSON.parse(jsonStr))
</script>
4.同步异步
同步:在原地需要有结果,才能继续向下
异步:交给浏览器去执行,不必在原地等待结果,主线程会先继续往下执行其他代码
异步:定时器,Ajax请求,事件绑定
5.回调函数
异步一般需要耗时,且不会阻塞主线进程代码往下执行
在JS中,只有用函数调用的方式,才能让某一段代码去执行
所以异步代码都有一个函数体,这个函数体里面代码都是等待这个异步任务有结果后执行
把一个函数当作实参传递进去,将来特定的时机,在调用的这个函数内,回调我们传入的函数调用,这个动作就叫回调函数
function theFn(fn){
fn()//代码执行到这句话,会回调theFn()里函数体执行,这个过程叫回调函数
}
theFn((=>{//此箭头函数作为实参值传递给了theFn的形参变量fn上
console.log('回调函数执行');
}))
6.回调地狱
回调函数中嵌套回调函数,不方便阅读和修改
举例
<script>
function myAjax(url, fn) {
let xhr = new XMLHttpRequest()
xhr.open('GET', url)
xhr.send()
xhr.addEventListener('load', () => {
fn(JSON.parse(xhr.response))
})
}
//1.请求省份列表
myAjax('http://ajax-api.itheima.net/api/province', res => {
let pname = res.data[5]
//2.请求城市列表
myAjax(`http://ajax-api.itheima.net/api/city?pname=${pname}`, res => {
let cname = res.data[9]
//3.请求地区列表
myAjax(`http://ajax-api.itheima.net/api/area?pname=${pname}&cname=${cname}`, res => {
console.log(res)
})
})
})
</script>
7.Promise语法学习
ES6新出的一个构造函数,为了解决回调地狱
语法:
let 变量 = new Promise((resolve,reject)=>{
//resolve和reject是Promise提供的两个函数
//写一些代码(同步/异步)都可以,你想返回出去结果
//resolve('成功的结果')
//reject('失败的结果')
})
变量.then(res=>{
//接收此Promise对象内,返回出来的成功结果
}).catch(err=>{
//接收此Promise对象内,返回出来的失败结果
})
运行:
1.new Promise后原地留下一个Promise对象(承诺),承诺将来会有一个成功/失败的结果给你返回使用
2.它会立即执行new Promise()小括号里所有代码
8.Promise的三种状态
- new Promise原地有个Promise§,状态:‘pending’(准备) 通过打印查看它的标记
2.立刻执行new Promise()里函数体所有代码,并准备resolve和reject函数
3.给Promise对象§,添加.then和.catch函数,等待结果
4.Promise对象内,当调用了resolve(),会把当前Promise对象,状态:‘fulfilled’(成功),内部会回调then()里面函数体执行
5.Promise对象内,当调用了reject(),会把当前Promise对象,状态:‘rejected’(失败),内部会回调.then()里面函数体执行
9.链式调用
let p = new Promise((resolve, reject) => {
setTimeout(() => {
resolve('成功1')
}, 2000)
})
let p2 = new Promise((resolve, reject) => {
setTimeout(() => {
resolve('成功2')
}, 2000)
})
p.then(res => {
console.log(res);//如果return一个promise对象,会被下一个then接收
return p2
}).then(res => {
console.log(res)
})
//两个promise一起打印
10.解决回调地狱
function myAjax(url) {
return new Promise((resolve, reject) => {
let xhr = new XMLHttpRequest()
xhr.open('GET', url)
xhr.send()
xhr.addEventListener('load', () => {
resolve(JSON.parse(xhr.response))
})
})
}
let pname=''
//1.拿到省份
let p=myAjax('http://ajax-api.itheima.net/api/province')
p.then(res=>{
pname = res.data[5]
//2.拿到城市
return myAjax('http://ajax-api.itheima.net/api/city?pname=${pname}')
}).then(res=>{
let cname = res.data[9]
return myAjax(`http://ajax-api.itheima.net/api/area?pname=${pname}&cname=${cname}`)
}).then(res=>{
console.log(res)
})
11.promise的方法
all方法
语法:
Promise.all()
作用:它把多个Promise对象合并成一个大的Promise对象
返回值:大的Promise对象
这个大的Promise对象的结果,还是一个数组
Promise.all([小Promise对象,小Promsie对象,小Promise对象])
特点:需要所有小的Promise对象成功后才会触发大的Promise对象成功的then
注意:万一有失败了,就会让大的Promise对象直接状态变成失败状态
race方法
语法:
Promise.all([小Promise对象,小Promsie对象,小Promise对象])
作用:它可以把多个Promise对象合并成一个大的Promise对象,有一个小的Promise对象成功了,这个大的Promise对象直接为成功状态(其他不看),大的Promise对象的结果,直接是成功的这个小的Promise对象的成功结果
四.ES8和EventLoop
1.async和await
语法:
async function 函数名(){
const result = await Promise对象
}
举例:
//aiait只能在被async修饰的函数内
let p=new Promise((resolve,reject)=>{
setTimeout(() => {
resolve('成功的值')
}, 2000);
})
async function myFn(){
const result = await p
console.log(result)
}
myFn()
const youFn= async()=>{
const result=await p
console.log(result)
}
youFn()
注意事项:
1.await必须用在被async修饰的函数内
2.async修饰后,此函数会被作为异步函数,在此函数中,遇到await会暂停代码往下,但不影响外面继续执行同步流程
3.await后面一般用Promise对象,但是也可以跟其他类型的数据。如果后面跟其他类型数据,把此值作为await提取成功的结果在原地直接使用;如果跟Promise对象,需要等待Promise对象内,resolve返回成功的结果,被await提取在原地使用
4.await不能获取到Promise对象内失败的结果,需要借助try+catch代码块来捕获
2.解决回调地狱
const getListFn = async () => {
const res = await myAjax('http://ajax-api.itheima.net/api/province')
const pname = res.data[5]
const res2 = await myAjax('http://ajax-api.itheima.net/api/city?pname=${pname}')
const cname=res.data[9]
const res3= myAjax(`http://ajax-api.itheima.net/api/area?pname=${pname}&cname=${cname}`)
console.log(res3)
}
3.EventLoop事件循环
js是单线程执行的脚本语言,同一时间只能做一件事
单线程执行任务队列,如果有一个耗时任务,后续会一直等待。防止这个问题,异步代码由js委托给宿主环境(node环境,浏览器)等执行
几个概念:
1.JS引擎(c++的代码),嵌入在浏览器软件内
作用:阅读+解析+执行,我们编写的js代码并运算结果
宿主:浏览器
2.js引擎里执行栈
(1)先从上到下逐行执行代码,遇到同步代码,等待结果并使用
(2)遇到异步代码,则交给宿主环境,主线程继续执行下一句
(3)宿主环境(异步任务)有了结果,会“先”把“回调函数”装入任务队列中排队
(4)执行栈空闲,会把任务队列里回调函数推入执行栈执行
3.事件循环
当执行栈空闲,调度任务队列里回调函数执行,再次空闲,再调度的循环过程,就叫事件循环
4.微任务和宏任务
微任务代码:宿主环境是JS引擎 Promise等 优先执行
宏任务代码:宿主环境是浏览器 script 事件 网络请求 定时器
异步任务的回调函数,才会放入任务队列中,等待被执行栈调用
微任务在宏任务之前被执行