1、XMLHttpRequest的使用
1.1 发起get无参请求
let xhr = new XMLHttpRequest()
xhr.open('get', 'http://www.itcbc.com:3006/api/getbooks')
- get方式不用设置请求头
- get方式没有请求体,但是也要发起请求
xhr.send()
- 监听异步对象的load事件
- 当数据响应成功且可以使用了就会触发
- 数据在xhr.response属性中
- 返回数据的默认类型是字符串,使用之前进行转换
- 数据格式是json格式
xhr.addEventListener('load', function() {
console.log(JSON.parse(xhr.response), typeof JSON.parse(xhr.response))
})
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<meta http-equiv="X-UA-Compatible" content="ie=edge" />
<title>Document</title>
</head>
<body>
<button>点我啊</button>
<script>
let btn = document.querySelector('button')
btn.addEventListener('click', function() {
let xhr = new XMLHttpRequest()
xhr.open('get', 'http://www.itcbc.com:3006/api/getbooks')
xhr.send()
xhr.addEventListener('load', function() {
console.log(xhr.response, typeof xhr.response)
console.log(JSON.parse(xhr.response), typeof JSON.parse(xhr.response))
})
})
</script>
</body>
</html>
1.2 发起get带参请求
- get方式的参数需要在url后面拼接
- 拼接的格式为: url?参数=值&参数=值(不要在参数中写空格)
xhr.open(
'get',
'http://www.itcbc.com:3006/api/getbooks?bookname=' + value
)
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<meta http-equiv="X-UA-Compatible" content="ie=edge" />
<title>Document</title>
</head>
<body>
<input type="text" />
<button>点我啊</button>
<script>
let btn = document.querySelector('button')
let input = document.querySelector('input')
btn.addEventListener('click', function() {
let value = input.value
let xhr = new XMLHttpRequest()
xhr.open(
'get',
'http://www.itcbc.com:3006/api/getbooks?bookname=' + value
)
xhr.send()
xhr.addEventListener('load', function() {
console.log(xhr.response, typeof xhr.response)
console.log(JSON.parse(xhr.response), typeof JSON.parse(xhr.response))
})
})
</script>
</body>
</html>
1.3 发起post请求
let xhr = new XMLHttpRequest()
xhr.open('post', 'http://www.itcbc.com:3006/api/addbook')
- 调用setRequestHeader方法设置请求头
- 属性名称:Content-Type
- 值:application/x-www-form-urlencoded(默认值)
xhr.setRequestHeader(
'Content-Type',
'application/x-www-form-urlencoded'
)
- 调用send方法设置请求体
- post方式的参数需要在请求体中传递
- 默认格式为key=value&key=value
xhr.send(
`bookname=${bookname.value}&author=${author.value}&publisher=${publisher.value}`
)
- 监听异步对象的load事件,通过response属性获取返回的内容
- 完整代码
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<meta http-equiv="X-UA-Compatible" content="ie=edge" />
<title>Document</title>
</head>
<body>
<form class="card-body bg-light" id="addForm">
<div class="input-group mb-3">
<div class="input-group-prepend">
<span class="input-group-text">书名</span>
</div>
<input
type="text"
class="form-control"
placeholder="请输入图书名称"
name="bookname"
/>
</div>
<div class="input-group mb-3">
<div class="input-group-prepend">
<span class="input-group-text">作者</span>
</div>
<input
type="text"
class="form-control"
placeholder="请输入作者名字"
name="author"
/>
</div>
<div class="input-group mb-3">
<div class="input-group-prepend">
<span class="input-group-text">出版社</span>
</div>
<input
type="text"
class="form-control"
placeholder="请输入出版社名称"
name="publisher"
/>
</div>
<input type="button" value="添加" class="btn btn-dark btnadd" />
</form>
<script>
let btnadd = document.querySelector('.btnadd')
let bookname = document.querySelector('[name="bookname"]')
let author = document.querySelector('[name="author"]')
let publisher = document.querySelector('[name="publisher"]')
btnadd.addEventListener('click', function() {
let xhr = new XMLHttpRequest()
xhr.open('post', 'http://www.itcbc.com:3006/api/addbook')
xhr.setRequestHeader(
'Content-Type',
'application/x-www-form-urlencoded'
)
xhr.send(
`bookname=${bookname.value}&author=${author.value}&publisher=${publisher.value}`
)
xhr.addEventListener('load', function() {
console.log(xhr.response)
})
})
</script>
</body>
</html>
2、封闭自己的ajax工具函数
2.1 简化参数及默认值处理
let method = option.method || 'get'
let url = option.url
if (!url) {
alert('一定要设置url')
return
}
let params = option.params
let data = option.data
2.2 创建一个异步对象
let xhr = new XMLHttpRequest()
2.3 处理get方式的params参数
2.4 设置请求行
xhr.open(method, url)
2.5 设置请求头和请求体
- 如果是post方式
- 要根据参数的类型进行请求头的设置和请求体的传递:
- 1.如果参数是key=value
if (typeof data == 'string') {
xhr.setRequestHeader('Content-Type', 'application/x-www-form-urlencoded')
xhr.send(data)
}
- 2.如果参数是formdata
else if (data instanceof FormData) {
xhr.send(data)
}
- 3.如果参数是对象
else {
xhr.setRequestHeader('Content-Type', 'application/json')
xhr.send(JSON.stringify(data))
}
- 如果是get方式
xhr.send()
2.6 接收响应
2.7 完整代码
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<meta http-equiv="X-UA-Compatible" content="ie=edge" />
<title>Document</title>
<script src="./lib/axios.js"></script>
<script src="./js/myajax.js"></script>
</head>
<body>
<input type="text">
<button class="search">查询指定名称的数据</button>
<script>
let input = document.querySelector('input')
let search = document.querySelector('.search');
search.addEventListener('click', function() {
axios({
method: 'post',
url: 'http://www.itcbc.com:3006/api/addbook',
data: `bookname=11&author=22&publisher=33`,
success: function(res) {
console.log(res);
}
})
})
</script>
</body>
</html>
function exchange(obj) {
let arr = []
for (let key in obj) {
arr.push(`${key}=${obj[key]}`)
}
return arr.join('&')
}
function axios(option) {
let method = option.method || 'get';
let url = option.url;
if(!url) {
alert('一定要设置url');
return
}
let params = option.params;
let data = option.data;
let success = option.success
let xhr = new XMLHttpRequest();
if(params && method.toLowerCase() == 'get') {
url = url + '?' + exchange(params);
}
xhr.open(method, url)
if(method.toLowerCase() == 'post') {
if(typeof data == 'string') {
xhr.setRequestHeader('Content-Type', 'application/x-www-form-urlencoded')
xhr.send(data)
}else if(data instanceof FormData) {
xhr.send(data)
} else {
xhr.setRequestHeader('Content-Type', 'application/json')
xhr.send(JSON.stringify(data))
}
}else{
xhr.send()
}
xhr.addEventListener('load', function() {
success(JSON.parse(xhr.response))
})
}
3、同源跨域-面试服务
- 3.1 同源跨域是浏览器的安全策略
- 可以正常的向服务器发起数据请求
- 服务器也会正常的响应
- 但是浏览器会阻止数据的返回
- 3.2 同源:协议,域名(IP),端口都一样,则同源,但凡有一个不一样则跨域
- 3.3 解决跨域的三种常见方案
- cors跨域:服务器端跨域
app.use('/', (req, res, next) => {
res.setHeader('Access-Control-Allow-Origin', '*')
res.setHeader('Access-Control-Allow-Credential', 'true')
res.setHeader('Access-Control-Allow-Methods', 'GET,POST,PUT,DELETE,OPTIONS')
next()
})
- jsonp跨域:浏览器跨域
- 本质是利用了Scirpt标签的src天然跨域特性
- 通过Script获取的内容会默认以js语法来解析
- 在发起请求的时候,传递一个函数名称,服务器返回函数调用形式并拼接相应的数据
- jsonp与异步对象没有任何的关系,它不是一个异步请求,只能发get请求
4、防抖
- 4.1 是指多次触发,只执行最后一次
- 4.2 将业务处理代码放到延迟器中
- 4.3 每次触发事件之后,先清除之前的延迟器,再重新添加延迟器,实现重新计时
- 4.4 代码演示:
let tid = null
input.addEventListener('input', function() {
clearTimeout(tid)
tid = setTimeout(() => {
axios({
url: 'http://www.itcbc.com:3006/api/getbooks'
}).then(res => {
console.log(res)
})
}, 2000)
})
5、节流
- 5.1 是指多次触发,只执行第一次
- 5.2 定义一个标识,如果满足条件才进行处理
- 5.3 在第一次操作之后,将标识进行重置,例如重置为false,再进行操作不再处理
- 5.4 本次操作完成了,将标识再重置为true
- 5.5 代码演示:
let flag = true
button.addEventListener('click', function() {
if(!flag){ return}
flag = false
setTimeout(() => {
console.log(123)
flag = true
}, 2000)
})