Ajax运行原理

Ajax相当于浏览器发送请求与接受响应的代理人,以实现不影响用户浏览页面的情况下,局部更新页面数据,从而提高用户体验

实现步骤

  1. 创建Ajax对象 new XMLHttpRequest()
  2. 告诉Ajax请求地址以及请求方式 open
  3. 发送请求 send方法
  4. 获取服务器端给予客户端的响应数据 onload 获取响应数据 responseText

查看答案

1
2
3
4
5
6
7
8
9
10
// 1. 创建ajax对象
var xhr = new XMLHttpRequest()
// 2. 告诉ajax对象发送的位置,和方式,第一个参数是请求方式,第二个请求地址
xhr.open('get', 'http://localhost:3000/first')
// 3. 发送请求
xhr.send()
// 4. 获取响应数据
xhr.onload = function(){
console.log(xhr.responseText);
}

响应的数据格式

  1. json对象作为响应数据的格式,请求返回的数据为json字符串
  2. 将json字符串转化为json对象

查看答案

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
// 1. 创建ajax对象
var xhr = new XMLHttpRequest()
// 2. 告诉ajax对象发送的位置,和方式,第一个参数是请求方式,第二个请求地址
xhr.open('get', 'http://localhost:3000/responseData')
// 3. 发送请求
xhr.send()
// 4. 获取响应数据,接受完请求后onload事件自动响应
xhr.onload = function(){
// 返回的是字符串类型
// console.log(xhr.responseText);
// 将json字符串转换为json对象
let respnseText = JSON.parse(xhr.responseText)
console.log(respnseText);
console.log(typeof respnseText);
// 将转换的json对象中的信息获取,并且将数据信息渲染到页面中
let str = `<h2>${respnseText.name}</h2>`
document.body.innerHTML = str
}

请求参数传递

  1. get请求xx.open('get',url)

查看答案

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
        let username =document.querySelector('#username')
let email =document.querySelector('#email')
let submit =document.querySelector('#submit')

// 给按钮添加一个点击事件
submit.onclick = function(){
// 获取从用户在表单中输入的值
let emaildata = email.value
let usernamedata = username.value
// 对获取到数据进行字符串的拼接
let str = `username=${usernamedata}&email=${emaildata}`
// 创建一个ajax对象
console.log(str);
let xhr = new XMLHttpRequest()
// 创建ajax对象的请求方式
xhr.open('get',`http://localhost:3000/get?${str}`)
xhr.send()
xhr.onload = function(){
console.log(xhr.responseText);
}
}
// res.send(req.query)
  1. get请求只能的请求头类型只能是application/x-www-form-urlencoded,并且在解析请求地址时通过 body-parser中的urlencoded()方法进行解析,get请求不能提交对象数据格式的

post请求方式

  1. 请求的方式为json时,如果要得到请求的json内容 需要使用 body-parser中的bodyPaser.json()方法
1
2
3
4
5
6
7
8
9
10
11
12
13
14
// 1. 创建ajax对象
var xhr = new XMLHttpRequest()
// 2. 告诉ajax对象发送的位置,和方式,第一个参数是请求方式,第二个请求地址
xhr.open('post', 'http://localhost:3000/json')
xhr.setRequestHeader('Content-Type','application/json');

// 3. 发送请求
xhr.send(JSON.stringify({name:'list',age:50}))
// 4. 获取响应数据,接受完请求后onload事件自动响应
xhr.onload = function(){
// 返回的是字符串类型
console.log(xhr.responseText);
// 将json字符串转换为json对象
}

ajax状态码

  1. 获取服务器端的响应
  2. 0 请求未初始化
  3. 1 请求以及简历,但是还没有发送
  4. 2 请求已经发送
  5. 3 表示请求正在处理中,部分代码可以使用
  6. 4 响应已经完成
  7. xhr.readyState 获取Ajax状态码 onreadystatechange事件
  8. onload比以上事件的请求方式更为效率

ajax错误处理

  1. xhr.status获取http状态码 400
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    var btn = document.getElementById('btn')
    // 当用户点击后发送错误请求
    btn.onclick=()=>{
    var xhr = new XMLHttpRequest()
    xhr.open('get','http://localhost:3000/error')
    // 对请求的http的状态码进行判断
    xhr.send();
    xhr.onload=()=>{
    console.log(xhr.status);
    if(xhr.status === 400){
    alert(xhr.responseText)
    }
    }
    }
  2. 404错误状态码 输入错误的情况较多 ,检测请求地址是否有误
  3. 500错误代码时服务器端错误
  4. 断网时无法触发onload事件,可以执行onerror()事件

注意ajax状态码表示的是服务器的请求过程的状态,http状态码表示的是请求的结果

低版本的缓存问题

  1. 在请求地址上加一个参数,并且保证每次请求参数的值不同即可

同步异步

  1. 封装一个简单的异步函数get
  2. get请求需要拼接到请求地址的后方,post请求放在send的方法中

查看答案

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
function ajax (params){
let xhr = new XMLHttpRequest();
let options = ''
params.data.forEach((v,i)=>{
params += v + '=' + params.data[i] + '&'
})
params.substr(0,params.length-1)
xhr.open(
params.type,params.url
)
xhr.send()
xhr.onload = ()=>{
params.success(xhr.responseText)
}
}
ajax({
type:'get',
url:'http://localhost:3000/first1',
data:{
name:'zs',
age:20
}
success:(data)=>{
console.log('这里是success函数'+data);
}
})
  1. 封装get请求和post请求参数的时候

查看答案

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
function ajax(params) {
let xhr = new XMLHttpRequest();
let options = ''
for (let attr in params.data) {
options += attr + '=' + params.data[attr] + '&'
}
options = options.substr(0, options.length - 1)
// console.log(options)
if (params.type === 'get') {
params.url = params.url + '?' + options
}
xhr.open(params.type, params.url)
if (params.type == 'post') {
let contentType = params.header['Content-Type']
xhr.setRequestHeader('Content-Type', contentType)
if (contentType === 'application/json') {
xhr.send(JSON.stringify(params.data))
} else {
xhr.send(options)
}
} else {
xhr.send()
}
xhr.onload = () => {
// 对http的状态码进行判断如果状态码为200则调用success函数,如果失败则调用error函数
if (xhr.status == 200) {
let responseHeader = xhr.getResponseHeader('Content-Type')
let resText = xhr.responseText
if (responseHeader.includes('application/json')) {
resText = JSON.parse(resText)
}
params.success(resText, xhr)
} else {
params.error(resText, xhr)
}
}
}
ajax({
type: 'get',
url: 'http://localhost:3000/responseData',
data: {
name: 'sz',
age: 20
},
header: {
'Content-Type': 'application/json'
// 'Content-Type':'application/x-www-form-urlencoded'
},
success: (data,xhr) => {
console.log('这里是success函数');
console.log(data);
console.log(xhr);
},
error: (data) => {
console.log('这里是error函数' + data);
}
})
  1. 获取请求中的数据 getResponseHeader()方法 在页面加载完成后调用onload事件中 如果获取到的请求类型为application/json类型,将json字符串以json对象的方式输出,使用方法JSON.parse()
  2. Object.assign() 如果目标对象和源对象有同名属性,或者多个源对象有同名属性,则后面的属性会覆盖前面的属性。如果该函数只有一个参数,当参数为对象时,直接返回该对象;当参数不是对象时,会先将参数转为对象然后返回。并且该方法是浅拷贝

查看答案

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
function ajax(params) {
// 给ajax设定一个默认值
let defaults = {
type: 'get',
url: '',
data: {},
header: {
'Content-Type': 'application/x-www-form-urlencoded'
},
success: (data) => {

},
error: (data) => {

}
}
// 使用Object.assign()方法 将之间的对象覆盖
Object.assign(defaults,params)
let xhr = new XMLHttpRequest();
let options = ''
for (let attr in params.data) {
options += attr + '=' + defaults.data[attr] + '&'
}
options = options.substr(0, defaults.length - 1)
// console.log(options)
if (defaults.type === 'get') {
defaults.url = defaults.url + '?' + options
}
xhr.open(defaults.type, defaults.url)
if (defaults.type == 'post') {
let contentType = defaults.header['Content-Type']
xhr.setRequestHeader('Content-Type', contentType)
if (contentType === 'application/json') {
xhr.send(JSON.stringify(defaults.data))
} else {
xhr.send(options)
}
} else {
xhr.send()
}
xhr.onload = () => {
// 对http的状态码进行判断如果状态码为200则调用success函数,如果失败则调用error函数
if (xhr.status == 200) {
let responseHeader = xhr.getResponseHeader('Content-Type')
let resText = xhr.responseText
if (responseHeader.includes('application/json')) {
resText = JSON.parse(resText)
}
defaults.success(resText, xhr)
} else {
defaults.error(resText, xhr)
}
}
}
ajax({
url: 'http://localhost:3000/responseData',
data: {
name: 'sz',
age: 20
},
success: (data, xhr) => {
console.log('这里是success函数');
console.log(data);
console.log(xhr);
}
})

模板引擎

  1. 使用模板引擎 art-template 在客户端的使用步骤

查看答案

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>模板引擎</title>
<script src="/js/art-template.js"></script>
</head>
<body>
<div class="container"></div>
<script type="text/html" id="idt">
<h1>{{username}} {{age}}</h1>
</script>
<script type="text/javascript">
let html = template('idt',{username:'zs',age:20})
document.querySelector('.container').innerHTML = html
</script>
</body>
</html>

验证邮箱

查看答案

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
<!DOCTYPE html>
<html lang="en">

<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>验证邮箱地址</title>
<script src="/js/ajax.js"></script>
<!-- <script src="/js/template.js"></script> -->
</head>

<body>
<style>
body {
background: -webkit-linear-gradient(left, rgb(216, 236, 235), rgb(241, 229, 241));
}

.box {
margin: 200px auto;
display: flex;
justify-content: center;
align-items: center;
flex-direction: column;
}

.email_login {
border-radius: 10px;
width: 400px;
height: 30px;
padding: 10px;
/* outline-color: aliceblue; */
}

.email_login:hover {
outline-color: bisque;
border: none;
}

.message {
background: rgb(221, 208, 208);
}

.success {
background-color: rgb(82, 82, 173);
}

.error {
background-color: rgb(226, 106, 106);
}
</style>
<div class="box">
<input type="email" class="email_login" value="" placeholder="请在此输入您要初测的邮箱账号!!">
<p class="message"></p>
</div>
<script type="text/javascript">
// 获取元素
let email = document.querySelector('.email_login')
let message = document.querySelector('p')
// 当输入框失去焦点时的事件
email.onblur = function () {
// console.log(e);
// 获取用户输入的值,对用户输入的值判断
let email_value = this.value
// 正则判断输入的值
let reg = /^[a-zA-Z0-9_-]+@[a-zA-Z0-9_-]+(\.[a-zA-Z0-9_-]+)+$/
if (!reg.test(email_value)) {
message.innerHTML = '输入的邮箱规则格式有误,请重新输入!!!'
message.className = 'message'
return;
}
ajax({
type: 'post',
url: "http://localhost:3000/emailbox",
data: {
email: email_value
},
success: function (response) {
if (response.message.includes('恭喜')) {
message.innerHTML = response.message
message.className = 'success'
} else {
message.innerHTML = response.message
message.className = 'error'
}
},
error: (res) => {
message.innerHTML = res.message
message.className = 'error'
}
});
}

</script>
</body>
</html>

请求路由

1
2
3
4
5
6
7
8
9
10
11
12
13
14
app.get('/emailbox',(req,res)=>{
if(req.query.email == 'iui9@qq.com'){
res.send({message:'您好邮箱已注册,请您重新输入!!'})
}else{
res.send({message:'恭喜您注册的邮箱可用!!!!'})
}
})
app.post('/emailbox',(req,res)=>{
if(req.body.email == 'iui9@qq.com'){
res.send({message:'您好邮箱已注册,请您重新输入!!'})
}else{
res.send({message:'恭喜您注册的邮箱可用!!!!'})
}
})

ajax封装

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
function ajax(params) {
// 给ajax设定一个默认值
let defaults = {
type: 'get',
url: '',
data: {},
header: {
'Content-Type': 'application/json'
},
success: (data) => {},
error: (data) => {}
}
// 使用Object.assign()方法 将之间的对象覆盖
Object.assign(defaults,params)
let xhr = new XMLHttpRequest();
let options = ''
for (let attr in params.data) {
options += attr + '=' + defaults.data[attr] + '&'
}
options = options.substr(0, defaults.length - 1)
// console.log(options)
if (defaults.type === 'get') {
defaults.url = defaults.url + '?' + options
}
xhr.open(defaults.type, defaults.url)
if (defaults.type == 'post') {
let contentType = defaults.header['Content-Type']
xhr.setRequestHeader('Content-Type', contentType)
if (contentType === 'application/json') {
xhr.send(JSON.stringify(defaults.data))
} else {
xhr.send(options)
}
} else {
xhr.send()
}
xhr.onload = () => {
// 对http的状态码进行判断如果状态码为200则调用success函数,如果失败则调用error函数
if (xhr.status == 200) {
let responseHeader = xhr.getResponseHeader('Content-Type')
let resText = xhr.responseText
if (responseHeader.includes('application/json')) {
resText = JSON.parse(resText)
}
defaults.success(resText, xhr)
} else {
defaults.error(resText, xhr)
}
}
}

搜索框内容自动提示

  1. 使用定时器的操作,延时对请求接口发送ajax请求,在每次请求之前将之前的定时器清除
  2. 设置防抖操作,对用户输入的值进行判断如果用户没有在手术框中输入内容,将提示信息 使用trim()函数,将文本框中的空格清除 阻止程序向下执行 return

三级联动(省市区)

  1. 接口地址:接口地址
  2. JSON.stringify() 方法可以将对象的数据存储在本地的内存中

查看答案

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
<!DOCTYPE html>
<html lang="en">

<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>三级联动 省市区</title>
<script src="js/ajax.js"></script>
<script src="js/art-template.js"></script>
</head>
<style>
body {
background-color: #ccc;
}

.box {
margin: 100px auto;
width: 500px;
height: 300px;
display: flex;
justify-content: center;
align-items: center;
}
</style>

<body>
<div class="box">
<div class="form_group">
<select name="" id="province">
<!-- <option value="">请选择省份</option> -->
</select>
</div>
<div class="form_group">
<select name="" id="city">
<option value="">请选择城市</option>
</select>
</div>
<div class="form_group">
<select name="" id="area">
<option value="">请选择县城</option>
</select>
</div>
</div>
</body>
<script type="text/html" id="provinceTpl">
<option value="">请选择省份</option>
{{each provices_list}}
<option value="{{$value.pindex}}">{{$value.provices_list}}</option>
{{/each}}
</script>
<script type="text/html" id="cityTpl">
<option value="">请选择城市</option>
{{each city_lists}}
<option value="">{{$value.citysName}}</option>
{{/each}}
</script>
<script>
// 封装一个函数
let All_lists = []
function getaddressData() {
ajax({
type: "get",
url: "https://cdn.jsdelivr.net/gh/Rr210/image@master/hexo/4/province1.json",
success: function (response) {
console.log(response);
All_lists = response.provinces
localStorage.setItem('address_data', JSON.stringify(response.provinces))
}
});
}
let province = document.querySelector('#province')
let city = document.querySelector('#city')
let addressData = localStorage.getItem('address_data')
if (!addressData) {
this.getaddressData()
} else {
All_lists = JSON.parse(addressData)
let provices_list = All_lists.map((v,i) => {
let arr = {provices_list:v.provinceName,pindex:i}
return arr
})
// console.log(provices_list);
let html = template('provinceTpl',{provices_list})
province.innerHTML = html
}
// 给省份选择框添加一个改变事件监听 select的变化
province.onchange = function(e){
let id = this.value
let city_lists = JSON.parse(addressData)[Number(id)].citys
// console.log(city_lists);
let html1 = template('cityTpl',{city_lists})
city.innerHTML = html1
}
</script>

</html>

FormData对象的作用

  1. 模拟HTML表单
  2. 异步上传二进制文件
  3. 本身是一个构造函数
  4. 使用formidable模块来解析FormData对象
  5. formData.get(‘属性名’),formData.set(‘属性名’,’属性值’),formData.delete(‘key’),formData.append(‘key’,’value’)
  6. 默认接收最后一个实例方法
  7. set方法和append方法的区别:在属性名已经存在的情况下,set会覆盖原来的键名的值,append会保留两个值

查看答案

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>FormData对象</title>
</head>
<body>
<form id="form">
<input type="text" name="username" id="" />
<input type="password" name="password" id="" />
<input type="button" id="btn" value="提交"/>
</form>
<script type="text/javascript">
// 获取按钮
var btn = document.querySelector('#btn')
var form = document.querySelector('#form')
btn.onclick = function(){
// 将普通的html表单转换为表单对象
let formData = new FormData(form)
let xhr = new XMLHttpRequest()
xhr.open('post','http://localhost:3000/formData')
// 发送ajax请求
xhr.send(formData)
// 监听xhr对象下面的onload事件
xhr.onload = function(){
if(xhr.status==200){
console.log(xhr.responseText);
}
}
}
</script>
</body>
</html>

配置路由

1
2
3
4
5
6
7
// 加入formidable模板
app.post('/formData',(req,res)=>{
const form = new formidable.IncomingForm();
form.parse(req,(err,fields,files)=>{
res.send(fields)
})
})

formData二进制上传

  1. get请求方式不能用于文件的上传

查看答案

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
<!DOCTYPE html>
<html lang="en">

<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>FormData二进制文件的上传</title>
</head>

<body>
<input type="file" name="" id="file" />
<script type="text/javascript">
let file = document.querySelector('#file')
file.onchange = function(){
let formData = new FormData()
formData.append('attrName',this.files[0])
var xhr = new XMLHttpRequest()
xhr.open('post','http://localhost:3000/up_file')
xhr.send(formData)
xhr.onload = function(){
if(xhr.status==200){
console.log(xhr.responseText);
}
}
}
</script>
</body>

</html>

上传进度条

  1. 使用上传事件中的onprogress事件

查看答案

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>上传进度条</title>
</head>
<style>
.progress_warp{
width: 800px;
height: 40px;
background-color: #ccc;
border-radius: 5px;
}
.progress_event{
border-radius: 5px;
width: 0;
height: 100%;
color: #fff;
background-color: rgb(53, 27, 68);
}
</style>
<body>
<input type="file" name="" id="file" />
<div class="progress_warp">
<div class="progress_event" style="width: 0%;" id="bar"></div>
</div>
<script type="text/javascript">
let file = document.querySelector('#file')
let bar = document.querySelector('#bar')
file.onchange = function(){
let formData = new FormData()
formData.append('attrName',this.files[0])
var xhr = new XMLHttpRequest()
xhr.open('post','http://localhost:3000/up_file')
xhr.upload.onprogress = function(e){
// console.log(e);
let bar_data = (e.loaded / e.total).toFixed(2) * 100 + '%'
bar.style.width = bar_data
bar.innerHTML = bar_data
}
xhr.send(formData)
xhr.onload = function(){
if(xhr.status==200){
console.log(xhr.responseText);
}
}
}
</script>
</body>
</html>

图片加载预览

查看答案

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>上传进度条</title>
</head>
<style>
.progress_warp{
width: 800px;
height: 40px;
background-color: #ccc;
border-radius: 5px;
}
.box_img{
padding: 20px;
}
.box_img img{
width: 100px;
border-radius: 10px;
}
.progress_event{
border-radius: 5px;
width: 0;
display: flex;
justify-content: center;
align-items: center;
font-size: 20px;
font-weight: 550;
margin: 10px 0;
height: 100%;
color: #fff;
background-color: rgb(53, 27, 68);
}
</style>
<body>
<input type="file" name="" id="file" />
<div class="box_img">

</div>
<div class="progress_warp">
<div class="progress_event" style="width: 0%;" id="bar"></div>
</div>
<script type="text/javascript">
let file = document.querySelector('#file')
let bar = document.querySelector('#bar')
let box_img = document.querySelector('.box_img')
file.onchange = function(){
let formData = new FormData()
formData.append('attrName',this.files[0])
var xhr = new XMLHttpRequest()
xhr.open('post','http://localhost:3000/up_file')
xhr.upload.onprogress = function(e){
// console.log(e);
let bar_data = (e.loaded / e.total).toFixed(2) * 100 + '%'
bar.style.width = bar_data
bar.innerHTML = bar_data
}
xhr.send(formData)
xhr.onload = function(){
if(xhr.status==200){
// console.log(xhr.responseText);
// 动态创建一个图片 将上传的文件的路径名称赋值给uploads
let img = document.createElement('img')
img.src= '/uploads' + JSON.parse(xhr.responseText).path
// 调用图片上传成功的事件onload
img.onload = function (){
box_img.appendChild(img)
}
}
}
}
</script>
</body>
</html>

ajax问题

  1. ajax不能向非同源服务器端发送请求
  2. 使用jsonp解决同源限制问题
  • 将不同源的服务器请求地址写在script标签的src属性中
  • 服务端响应数据必须是以一个函数的调用
  • 在客户端全局作用域下定义函数fn(在script标签的上面)
  • 在函数内部对服务器端返回的数据进处理

post请求格式

  1. 必须有请求头:content-type:application/x-www-form-unlencoded

    查看解析

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    <!DOCTYPE html>
    <html lang="en">

    <head>
    <meta charset="UTF-8">
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>post请求的两种方式</title>
    </head>

    <body>
    <!-- 第一种使用url形式的请求方式 -->
    <!-- <script type="text/javascript">
    let xhr = new XMLHttpRequest()
    xhr.open('post', 'http://localhost:3000/post')
    xhr.setRequestHeader('Content-Type', 'application/x-www-form-urlencoded')
    params = "name=zs&age=12"
    xhr.send(params)
    xhr.onload = function () {
    console.log(xhr.responseText);
    }
    </script> -->
    <!-- 第二种使用json形式 -->
    <script type="text/javascript">
    let xhr = new XMLHttpRequest()
    xhr.open('post', 'http://localhost:3000/post')
    xhr.setRequestHeader('Content-Type', 'application/json')
    params = {
    name: 'zs',
    age: 2
    }
    xhr.send(JSON.stringify(params))
    xhr.onload = function () {
    console.log(xhr.responseText);
    }
    </script>
    </body>
    </html>

jsonp请求封装

查看客户端

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
<!DOCTYPE html>
<html lang="en">

<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>jsonp的调用</title>
</head>

<body>
<button id="btn1">jsonP提交</button>
<button id="btn2">jsonP提交</button>
<script>
let btn1 = document.getElementById('btn1')
let btn2 = document.getElementById('btn2')
btn2.onclick = function () {
jsonP({
url: 'http://localhost:3000/better',
data:{
name:'zs',
age:23
},
success: (e) => {
console.log(e)
console.log(123)
}
})
}
// 封装一个jsonP函数
function jsonP(e) {
var script = document.createElement('script')
// 将传递的data取出来
params = ''
for(let arr in e.data){
params+=`&${arr}=${e.data[arr]}`
}
// 设置window下的随机函数名
fName = 'myjson' + Math.random().toString().replace('.', '')
// 设置src中的请求地址
window[fName] = e.success
script.src = e.url + `?callback=${fName+params}`
document.body.appendChild(script)
script.onload = function () {
document.body.removeChild(script)
}
}
</script>
</body>
</html>

查看服务器

}

1
2
3
4
5
6
app.get('/better',(req,res)=>{
// const fName = req.query.callback
// const result = fName + '({name:"zs"})'
// res.send(result)
res.jsonp({name:'zs',age:98})
})

腾讯天气API

查看解析

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
<!DOCTYPE html>
<html lang="en">

<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<script src="https://cdn.jsdelivr.net/gh/Rr210/hexofixed@v0.47/js/jquery-3.5.1.min.js"></script>
<link rel="stylesheet"
href="https://cdn.jsdelivr.net/gh/Rr210/hexofixed@frame/frame/bootstrap/3/css/bootstrap.min.css">
<script src="https://cdn.jsdelivr.net/gh/Rr210/hexofixed@frame/frame/bootstrap/3/js/bootstrap.min.js"></script>
<script src="/js/art-template.js"></script>
<title>Document</title>
</head>
<style>
.ta{
margin: 100px;
}
th{
text-align: center;
}
</style>
<body>
<div class="ta table-responsive">
<table class="table table-striped table-bordered table-hover text-center">
<thead>
<tr>
<th>degree</th>
<th>update_time</th>
<th>weather</th>
<th>weather_code</th>
<th>weather_short</th>
<th>wind_direction</th>
<th>wind_power</th>
</tr>
</thead>
<tbody id='html'></tbody>
</table>
</div>
<script src="/js/jsonp.js"></script>
<script type="text/html" id="tpl">
{{each info}}
<tr>
<td>{{$value.degree + '°'}}</td>
<td class="">{{dateFormat($value.update_time)}}</td>
<td>{{$value.weather}}</td>
<td>{{$value.weather_code}}</td>
<td>{{$value.weather_short}}</td>
<td>{{$value.wind_direction}}</td>
<td>{{$value.wind_power+'级'}}</td>
</tr>
{{/each}}
</script>
<script>
let datas = document.getElementById('html')
// 构造一个date函数
function dateFormat(dates){
let year = dates.substr(0,4)
let mounth = dates.substr(4,2)
let day = dates.substr(6,2)
let hour = dates.substr(8,2)
let min = dates.substr(10,2)
return `${year}-${mounth}-${day} ${hour}:${min}`
}
// 将自定义函数开放到模板中
template.defaults.imports.dateFormat = dateFormat
jsonP({
url: 'https://wis.qq.com/weather/common',
data: {
source: 'pc',
weather_type: 'forecast_1h|forecast_24h',
province: '山西省',
city: '晋中市'
},
success: (e) => {
// console.log(e);
let html = template('tpl', { info: e.data.forecast_1h })
// console.log(html);
datas.innerHTML = html
}
})
</script>
</body>

</html>

cors 跨域资源共享

  1. 使用express方法 设置请求的报文
  2. 使用express模块中的中间件拦截请求 app.use
  3. 设置服务器的响应报文 res.header('Access-Control-Allow-Origin','*')
  4. 设置请求方法 res.header('Access-Control-Allow-Method':'get,post')
  5. 注意在使用中间件拦截时 一定要注意放行,否则无法执行后面的内容 next()

查看解析

}

1
2
3
4
5
app.use((req,res,next)=>{
res.header('Access-Control-Allow-Origin','*')
res.header('Access-Control-Allow-Methods','get,post')
next()
})

cookie复习

  1. withCredentials:指定在涉及到跨域请求时,是否携带cookie信息,默认值为false
  2. Access-Control-Allow-Credentials:true 允许客户端发送请求时携带cookie

查看解析

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
<!DOCTYPE html>
<html lang="en">

<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>设置cook信息</title>
</head>

<body>
<form id="loginForm">
<input type="text" placeholder="用户名" name="username" />
<input type="password" placeholder="密码" name="pwd" />
</form>
<button id="logined">登录</button>
<button id="checklogin">检测登录</button>
<script>
let loginform = document.getElementById('loginForm')
let logined = document.getElementById('logined')
let checklogin = document.getElementById('checklogin')
// 监听请求
logined.onclick = function () {
let formData = new FormData(loginform)
let xhr = new XMLHttpRequest()
xhr.open('post', 'http://localhost:3000/logins')
xhr.withCredentials = true
xhr.send(formData)
xhr.onload = function () {
console.log(xhr.responseText);
}
}
checklogin.onclick = function(){
let xhr = new XMLHttpRequest()
xhr.open('get', 'http://localhost:3000/checklogin')
// xhr.withCredentials = true
xhr.send()
xhr.onload = function () {
console.log(xhr.responseText);
}
}
</script>
</body>
</html>

查看解析

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
app.post('/logins', (req, res) => {
// console.log(res);
const form = new formidable.IncomingForm();
form.parse(req, (err, fields, files) => {
console.log(fields);
if (fields.username == '123' && fields.pwd == '123') {
req.session.isLogin = true
res.send({ message: '登录成功', code: 1 })
} else {
res.send({ message: '登录失败', code: -1 })
}
// res.send(fields)
})
// 解析formdata
})
app.get('/checklogin', (req, res) => {
if (req.session.isLogin) {
res.send({ message: '当前已登录' })
}else{
res.send({message:'当前未登录'})
}
})

jquery中的$.ajax()

  1. 请求参数时,默认为application/x-www-form-encoded
  2. 如果使用json对象,需要将json对象转换成json字符串,并且将类型设置为application/json
  3. beforeSend 表示在发送ajax请求前执行的 可在其中测试传递的参数,不满足条件可以使用return false

seralize方法

  1. 将表单中的数据自动拼接成字符串类型,如:name=zs&age=12
  2. 使用sealizeArray()方法将用户输入的内容转换成数组形式
  3. 封装一个函数使数组形式转换为json对象

查看解析

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
<!DOCTYPE html>
<html lang="en">

<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>使用jquery中的serialize方法</title>
</head>

<body>
<form id="form">
<input type="text" name="username" placeholder="用户名" />
<input type="password" name="pwd" placeholder="用户名" />
<input type="submit" value="提交" />
</form>
<script src="https://cdn.jsdelivr.net/gh/Rr210/hexofixed@v0.47/js/jquery-3.5.1.min.js"></script>
<script>
$('#form').on('submit', function () {
// let params = $("#form").serialize()
// console.log(params);
// return false;
serializeObject($(this))
return false
})
function serializeObject(obj) {
let result = {}
let params = obj.serializeArray()
// console.log(params)
$.each(params,(index,item)=>{
result[item.name] = item.value
})
console.log(result);
return result
}
</script>
</body>

</html>

$.ajax() 发送jsonp请求

  1. dataType:'jsonp'
  2. jsonCallback:'fnName' 指定函数名称
  3. jsonp:'cb' 修改callback名称

查看解析

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>使用jquery中的jsonp方法</title>
<script src="https://cdn.jsdelivr.net/gh/Rr210/hexofixed@v0.47/js/jquery-3.5.1.min.js"></script>
</head>
<body>
<button id="btn">
发送请求
</button>
<script>
// $('#btn').on('click',function(){
// $.ajax({
// type:'get',
// url:'jsonp',
// success:(res)=>{
// console.log(res);
// }
// })
// })
$('#btn').on('click',function(){
$.ajax({
url:"/jsonp",
type:'get',
dataType:'jsonp',
success:(res)=>{
console.log(res);
}
})
})
</script>
</body>
</html>

todoList 案例

  1. GitHub地址:【github
  2. 使用技术node.js+express+mongoose

ajax请求

  1. ajaxStart方法为当页面中有ajax请求时触发
  2. ajaxComplete 方法为当页面中ajax请求完成时触发

RESful风格

  1. 规范API设计
  2. get/put/delete/
  3. req.params 获取get请求参数 地址为:user/:id

XML是可扩展标记语言

  1. 作用是传输和存储数据
  2. XML DOM 即XML文档对象模型

查看解析

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>XML的获取</title>
</head>
<body>
<button id="btn">发送请求</button>
<div class="container"></div>
<script type="text/javascript">
let btn = document.getElementById('btn')
let container = document.getElementsByClassName('container')
btn.onclick = function(){
let xhr = new XMLHttpRequest()
xhr.open('get','https://u.mr90.top/other/atom.xml')
xhr.send()
xhr.onload = function(){
let xmlDocument = xhr.responseXML
let title = xmlDocument.querySelectorAll('entry title')
// 使用map函数将原来数组中的元素提取出来 组成新的数组
let arr = [...title]
let title_all = arr.map(v=>v.innerHTML)
let html = template('tit',{title_all})
// 将获取的html数组通过模板方法渲染到页面上
container.innerHTML = html
}
}
</script>
</body>
</html>

数组转换

  1. 使用Array.prototype.slice.call(nodes,0) nodes为伪数组
  2. 使用es6中的方法 [...arr] 或者使用Array.from(obj)的方法进行转换