301 lines
9.1 KiB
Markdown
301 lines
9.1 KiB
Markdown
# ajax
|
||
|
||
> `XMLHttpRequest`(简称 `XHR`)的发明是为了解决早期 Web 开发中的一个关键问题:**如何在不刷新整个页面的情况下,与服务器进行异步通信**
|
||
|
||
## xhr
|
||
|
||
### get
|
||
|
||
```html
|
||
<!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 method="post" action="#">
|
||
姓名: <input type="text" id="name" name="name" /> <span id="msg"></span><br />
|
||
年龄: <input type="number" id="age" name="age" /><br />
|
||
<!-- type="submit":submit有默认的提交行为,现在用一用而已,以后避免使用它 -->
|
||
<input type="submit" value="注册" />
|
||
</form>
|
||
<script>
|
||
document.querySelector('#name').onchange = function () {
|
||
let name = this.value
|
||
|
||
//向后台请求数据, 局部刷新
|
||
//1.创建异步对象
|
||
let xhr = new XMLHttpRequest()
|
||
|
||
//2.确定请求地址和请求参数
|
||
xhr.open('get', 'http://127.0.0.1:3002/validataUserName?name=' + name)
|
||
|
||
//3.通过send方法可以发起请求, send(string):string仅用于 POST 请求
|
||
xhr.send(null)
|
||
//这个时候在浏览器的response里已经可以看到数据返回, 只是没有接收处理
|
||
|
||
// 4.异步对象接收数据
|
||
xhr.onload = function () {
|
||
// console.log(this) 数据在response方法里面, 是字符串格式,再转成对象, 用键的方法取提示
|
||
document.querySelector('#msg').innerHTML = JSON.parse(this.response).msg
|
||
}
|
||
}
|
||
</script>
|
||
</body>
|
||
</html>
|
||
|
||
```
|
||
|
||
### post
|
||
|
||
```js
|
||
<!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 method="post" action="#" enctype="application/x-www-form-urlencoded">
|
||
姓名: <input type="text" name="username" id="username"><br>
|
||
密码: <input type="password" name="password" id="password"><br>
|
||
phone: <input type="number" name="phone" id="phone"><br>
|
||
<input type="button" id="button" value="注册"></input><span id="msg"></span>
|
||
</form>
|
||
<script>
|
||
//大量的数据, 比如图片的传递, 不是通过url, 而是在xhr.send('post', 数据)
|
||
//发送的也是键值对
|
||
//post方式的请求, 有参数的时候就必须设置请求头, 进行编码格式的处理, 否则参数传递了, 服务器也无法获取
|
||
//get方式的请求,不需要设置请求头, 默认utf-8
|
||
//xhr.setRequestHeader('Content-Type', 'application/x-www-form-urlencoded')
|
||
//form表单里面有参数enctype="application/x-www-form-urlencoded"
|
||
// button 写在form 没有指定类型, 默认是submit, 会默认提交表单刷新页面
|
||
//写成<button type="button"><button/>或者改成<input type="button" /> 或者a标签
|
||
//preservel log, 保留请求日志,跳转页面的时候勾选上,可以看到跳转前的请求
|
||
|
||
|
||
document.querySelector('#button').onclick = function () {
|
||
let username = document.querySelector('#username').value
|
||
let password = document.getElementById('password').value
|
||
let phone = document.getElementById('phone').value
|
||
console.log(username, password, phone)
|
||
|
||
// 1.创建异步对象
|
||
let xhr = new XMLHttpRequest
|
||
|
||
//2.1 设置请求行: 请求方式 请求路径 get把键值对拼接到路径后面, post设置请求体
|
||
xhr.open('post', 'http://127.0.0.1:3002/doRegister')
|
||
|
||
//2.2 设置请求头, get不需要设置, post定义网络文件的类型和编码
|
||
xhr.setRequestHeader('Content-Type', 'application/x-www-form-urlencoded')
|
||
//application/x-www-form-urlencoded: <form encType=””>中默认的encType
|
||
|
||
//2.3 设置请求体: get内容为null, post内容为键值对
|
||
xhr.send(`username=${username}&password=${password}&phone=${phone}`)
|
||
|
||
xhr.onload = function () {
|
||
document.querySelector('#msg').innerHTML = JSON.parse(this.response).msg
|
||
console.log(JSON.parse(this.response))
|
||
}
|
||
}
|
||
</script>
|
||
</body>
|
||
|
||
</html>
|
||
```
|
||
|
||
## ajax
|
||
|
||
### 封装 ajax
|
||
|
||
```js
|
||
let $ = {
|
||
//option.type 请求类型
|
||
//option.url 请求地址
|
||
//option.data 请求体
|
||
//option.dataType 响应数据类型
|
||
//option.success 处理函数
|
||
|
||
/*
|
||
优化: 1. 传入的参数可以是键值对, 也可以是对象, 自动转成键值对
|
||
2. 响应的数据可以是json, 也可以是xml, 默认是对象
|
||
*/
|
||
|
||
//封装一个把对象转成键值对的方法
|
||
getParams: function (data) {
|
||
if (data) {
|
||
//如果是对象, 转成键值对
|
||
if (typeof data == 'object') {
|
||
let str = ''
|
||
//遍历对象, 拼接
|
||
for (let key in data) {
|
||
str += key + '=' + data[key] + '&'
|
||
}
|
||
//去掉最后多余的&
|
||
return str.substr(0, str.length - 1)
|
||
} else {
|
||
//如果是字符串, 直接返回
|
||
return data
|
||
}
|
||
} else {
|
||
//如果没有传递参数, 返回字符串
|
||
return ''
|
||
}
|
||
},
|
||
|
||
//es6新的语法糖
|
||
ajax(option) {
|
||
let type = option.type || 'get'
|
||
let url = option.url
|
||
|
||
// console.log(this)
|
||
let data = this.getParams(option.data)
|
||
|
||
let dataType = option.dataType || 'text/html'
|
||
let success = option.success
|
||
|
||
//1. 初始化异步对象
|
||
let xhr = new XMLHttpRequest()
|
||
|
||
//2.1 请求行
|
||
//当为get的时候, 请求行拼接url, 请求体为null
|
||
if (type.toLowerCase() == 'get') {
|
||
url += `?${data}`
|
||
data = null
|
||
}
|
||
xhr.open(type, url)
|
||
|
||
//2.2设置请求头
|
||
if (type.toLowerCase() == 'post') {
|
||
xhr.setRequestHeader('Content-Type', 'application/x-www-form-urlencoded')
|
||
}
|
||
|
||
//2.3设置请求体
|
||
xhr.send(data)
|
||
|
||
//3.处理函数
|
||
xhr.onload = function () {
|
||
//3.1 判断用户需要的格式, 接收事件请求响应并转化
|
||
let res = null
|
||
if (dataType.toLowerCase() == 'json') {
|
||
res = JSON.parse(this.response)
|
||
} else if (dataType.toLowerCase() == 'xml') {
|
||
res = this.responseXML
|
||
} else {
|
||
res = this.response
|
||
}
|
||
//3.2 调用函数
|
||
//逻辑短路, 没有传入函数直接跳过
|
||
success && success(res)
|
||
}
|
||
},
|
||
}
|
||
```
|
||
|
||
### 使用
|
||
|
||
```html
|
||
<!DOCTYPE html>
|
||
<html lang="en">
|
||
|
||
<head>
|
||
<meta charset="UTF-8">
|
||
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
||
<title>Document</title>
|
||
<script src="./js/ajax.js"></script>
|
||
</head>
|
||
|
||
<body>
|
||
<form method="post" action="#" enctype="application/x-www-form-urlencoded">
|
||
姓名: <input type="text" name="username" id="username"><br>
|
||
密码: <input type="password" name="password" id="password"><br>
|
||
phone: <input type="number" name="phone" id="phone"><br>
|
||
<input type="button" id="button" value="注册"></input><span id="msg"></span>
|
||
</form>
|
||
<script>
|
||
document.querySelector('#button').onclick = function () {
|
||
let username = document.querySelector('#username').value
|
||
let password = document.getElementById('password').value
|
||
let phone = document.getElementById('phone').value
|
||
|
||
$.ajax({
|
||
type: 'post',
|
||
url: 'http://127.0.0.1:3002/doRegister',
|
||
data: {
|
||
'username': username,
|
||
'password': password,
|
||
'phone': phone
|
||
},
|
||
dataType: 'json',
|
||
// success(res) {
|
||
// document.querySelector('#msg').innerHTML = res.msg
|
||
// }
|
||
})
|
||
}
|
||
</script>
|
||
</body>
|
||
|
||
</html>
|
||
```
|
||
|
||
### formdata 文件上传
|
||
|
||
```html
|
||
<!DOCTYPE html>
|
||
<html lang="en">
|
||
<head>
|
||
<meta charset="UTF-8" />
|
||
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
|
||
<title>Document</title>
|
||
<script src="./js/jquery-1.12.4.min.js"></script>
|
||
<style>
|
||
div img {
|
||
height: 100px;
|
||
width: 100px;
|
||
background-color: #eee;
|
||
object-fit: contain;
|
||
/* https://www.jianshu.com/p/a2ce70fa9584 */
|
||
}
|
||
</style>
|
||
</head>
|
||
|
||
<body>
|
||
<form action="">
|
||
<input type="file" name="img" id="img" class="myimg" /> <br />
|
||
<div>
|
||
<img src="" alt="" class="myphoto" />
|
||
</div>
|
||
<input type="button" value="单击上传文件" class="btn" />
|
||
</form>
|
||
|
||
<script>
|
||
$(function () {
|
||
$('#img').on('change', function () {
|
||
console.log('aa')
|
||
let formdata = new FormData()
|
||
let myfile = $('#img')[0].files[0]
|
||
console.log(myfile)
|
||
formdata.append('img', myfile)
|
||
$.ajax({
|
||
type: 'post',
|
||
url: 'http://127.0.0.1:3002/uploadFile',
|
||
data: formdata,
|
||
dataType: 'json',
|
||
processData: false,
|
||
contentType: false,
|
||
success: function (res) {
|
||
$('.myphoto').attr('src', 'http://127.0.0.1:3002/images/' + res.img)
|
||
},
|
||
})
|
||
})
|
||
})
|
||
</script>
|
||
</body>
|
||
</html>
|
||
``` |