简介:Ajax即A synchronous J avascript A nd X ML在 2005年被Jesse James Garrett提出的新术语…
第一章 HTTP协议 HTTP协议:超文本传输协议,协议详细规定了浏览器和万维网服务器之间互相通信的规则
请求报文 从上到下为:
请求行:你的url + 协议版本
请求头:要访问的域名
空行
请求体:表单数据等等
1 2 3 4 5 6 7 GET /s?ie=utf-8&rsv_enter=1&rsv_dl=tb HTTP/1.1 Host: www.baidu.comCookie : name=guiguContent-type : application/x-www-form-urlencodedUser-Agent : chrome 83username=admin &password =admin
响应报文 从上到下为:
行:协议版本 + 响应状态码 + 响应字符串
头:对响应体内容做一些描述
空行
体:具体html代码
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 HTTP/1.1 200 OK Content-Type: text/html;charset=utf-8 Content-length: 2048 Content-encoding: gzip <html> <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>Document</title> </head> <body> <div id="root"></div> </body> </html>
第二章 原生Ajax Ajax简介
XML简介
Ajax的特点 优点
可以无需刷新页面与服务器端进行通信
允许你根据用户触发的事件来更新部分页面内容
缺点
没有浏览历史,不能回退
存在跨域问题
SEO不友好
Ajax的简单使用 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 31 32 33 34 35 36 37 38 39 40 41 42 43 44 <body > <button > Click me to send request</button > <div id ="result" > </div > <script > const btn = document .getElementsByTagName('button' )[0 ] const result = document .getElementById('result' ) btn.onclick = function ( ) { const xhr = new XMLHttpRequest() xhr.open('GET' , 'http://127.0.0.1:8000/example' ) xhr.send() xhr.onreadystatechange = function ( ) { if (xhr.readyState === 4 ){ if (xhr.status >= 200 && xhr.status < 300 ){ console .log(xhr.status) console .log(xhr.statusText) console .log(xhr.getAllResponseHeaders()) console .log(xhr.response) result.innerHTML = xhr.response }else { console .log(xhr.status) console .log(xhr.statusText) console .log(xhr.getAllResponseHeaders()) console .log(xhr.response) } } } } </script > </body >
在这里的服务端为:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 const express = require ('express' )const app = express()app.get('/example' ,(request, response )=> { response.setHeader('Access-Control-Allow-Origin' ,'*' ) response.send('message' ) }) app.listen(8000 , ()=> { console .log('http://127.0.0.1:8000' ) })
我们可以观察得知:在html页面获取请求,然后再根据服务端发送过来的response来进行重新渲染
POST型 我们需要先安装pody-parse
1 2 npm init -ynpm i -S body-parser
下面是代码部分
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 <body > <button > Click me to send request</button > <div id ="result" > </div > <script > const result = document .getElementById('result' ) result.addEventListener('mouseover' ,()=> { const xhr = new XMLHttpRequest() xhr.open('POST' , 'http://127.0.0.1:8000/example' ) xhr.setRequestHeader('Content-type' ,'application/x-www-form-urlencoded' ) xhr.send('a=100&b=200' ) xhr.onreadystatechange = () => { if (xhr.readyState === 4 ){ if (xhr.status >= 200 && xhr.status < 300 ){ result.innerHTML = xhr.response } } } }) </script > </body >
1 2 3 4 5 app.post('/example',(request, response)=>{ response.setHeader('Access-Control-Allow-Origin','*') response.send('message post') })
第三章 Ajax与json格式数据 js文件部分 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 const express = require ('express' )const app = express()app.all('/json-server' ,(request, response )=> { response.setHeader('Access-Control-Allow-Origin' ,'*' ) const data = { name : 'Linkaidi' } let str = JSON .stringify(data) response.send(str) }) app.listen(9000 , ()=> { console .log('http://127.0.0.1:9000' ) })
在此,我们可以开设另一个js文件来存放数据,或者我们可以使用mongoose
HTML文件部分 就只是普通的文件,多了一点转换json格式的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 <body > <button > Click me to send request</button > <div id ="result" > </div > <script > window .onkeydown = function ( ) { const result = document .getElementById('result' ) const xhr = new XMLHttpRequest() xhr.responseType = 'json' xhr.open('GET' , 'http://127.0.0.1:9000/json-server' ) xhr.send() xhr.onreadystatechange = function ( ) { if (xhr.readyState === 4 ){ if (xhr.status >= 200 && xhr.status < 300 ){ result.innerHTML = xhr.response.name console .log(xhr.response) } } } } </script > </body >
第四章 超时和网络异常 自动取消资源获取 有时候我们不会立刻获取到服务器的数据,这时候我们需要设置一个超时机制,超时就让用户自行检查网络
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 <body > <button > Click me to send request</button > <div id ="result" > </div > <script > const btn = document .getElementsByTagName('button' )[0 ] const result = document .getElementById('result' ) btn.addEventListener('click' , function ( ) { const xhr = new XMLHttpRequest() xhr.timeout = 2000 xhr.ontimeout = () => { alert('请求超时' ) } xhr.onerror = () => { alert('没有网络!请重试!' ) } xhr.open('GET' , 'http://127.0.0.1:9000/delay' ) xhr.send() xhr.onreadystatechange = () => { if (xhr.readyState === 4 ){ if (xhr.status >= 200 && xhr.status < 300 ){ result.innerHTML = xhr.response } } } }) </script > </body >
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 const express = require ('express' )const app = express()app.all('/delay' ,(request, response )=> { response.setHeader('Access-Control-Allow-Origin' ,'*' ) setTimeout (()=> { response.send('delay' ) }, 5000 ) }) app.listen(9000 , ()=> { console .log('http://127.0.0.1:9000' ) })
手动取消 我们只需要在另一个组件绑定xhr.abort()函数就好
注意事项:
第五章 请求重复发送 请求重复发送时会造成一些延迟问题,如果有设置超时那么可能会产生丢失数据
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 <body > <button > Click me to send time over request</button > <button > Click me to cancel request</button > <button > Click me to send request</button > <div id ="result" > </div > <script > const btn2 = document .getElementsByTagName('button' )[2 ] let xhr = null btn2.addEventListener('click' , function ( ) { const xhr = new XMLHttpRequest() xhr.timeout = 2000 xhr.ontimeout = () => { alert('请求超时了' ) } xhr.open('GET' , 'http://127.0.0.1:9000/server' ) xhr.send() xhr.onreadystatechange = () => { if (xhr.readyState === 4 ){ if (xhr.status >= 200 && xhr.status < 300 ){ result.innerHTML = xhr.response } } } }) </script > </body >
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 const express = require ('express' )const app = express()app.all('/server' ,(request,response )=> { response.setHeader('Access-Control-Allow-Origin' ,'*' ) setTimeout (()=> { response.send('延时发送' ) }, 3000 ) }) app.listen(9000 , ()=> { console .log('http://127.0.0.1:9000' ) })
由于js的单线程性质,会导致请求丢失:
我们的解决方案:设置一个参数作为标识变量,如果已经发过该请求,就自行取消其他的请求,直到该请求发送成功
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 btn2.addEventListener('click' , function ( ) { if (isSending){ xhr.abort() } xhr = new XMLHttpRequest() isSending = true xhr.timeout = 2000 xhr.ontimeout = () => { alert('请求超时了' ) } xhr.open('GET' , 'http://127.0.0.1:9000/server' ) xhr.send() xhr.onreadystatechange = () => { if (xhr.readyState === 4 ){ isSending = false if (xhr.status >= 200 && xhr.status < 300 ){ result.innerHTML = xhr.response } } } })
在此需要有几点要注意的:
不管按多少次按钮,所有的XMLHttpRequest都必须是同一个,才可以取消,不然就是一直在进行创建导致重复
状态的处理需要自行理解
不同的请求我们最好在不同的js文件里面写,这样XMLHttpRequest就不会公用导致另一边的请求被取消
第六章 jQuery发送Ajax请求 jQuery的引入 1 <script src ="https://cdn.bootcdn.net/ajax/libs/jquery/3.6.0/jquery.min.js" > </script >
jQuery的部分使用
get的使用及参数说明:
第一个参数:url地址
第二个参数:传入的表单数据,对象形式包装,与之前的send(‘a=100&b=200’)是一样的
第三个参数:回调函数,用于写执行get成功之后会发生的事情,通常有从服务端获取到的数据data
第四个参数:决定data为什么格式
1 2 3 4 5 6 7 <script> $('button').eq(0).click(() => { $.get('http://127.0.0.1:9000/server',{a: 100, b: 200}, (data) => { console.log(data) }, 'json') }) </script>
post也是同理
1 2 3 4 5 6 7 8 <script> // 这是获取到的数据转换成json格式 $('button').eq(0).click(() => { $.post('http://127.0.0.1:9000/server',{a: 100, b: 200}, (data) => { console.log(data) }, 'json') }) </script>
jQuery的通用方法发送Ajax请求 直接将要获取的数据封装成一个对象来进行ajax请求
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 $('button' ).eq(1 ).click(() => { $.ajax({ url : 'http://127.0.0.1:9000/server' , dataType : 'json' , data : {a : 100 , b : 200 }, type : 'GET' , success : (data ) => { console .log(data) }, error : () => { console .log('出错了' ) }, timeout : 2000 , headers : {c : 300 , d : 400 } }) })
第七章 Axios工具包 安装引入Axios
1 <script src ="https://cdn.bootcdn.net/ajax/libs/axios/0.21.1/axios.js" > </script >
使用Axios示例 使用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 <body > <button > GET</button > <button > POST</button > <button > AJAX</button > <script > const btns = document .querySelectorAll('button' ) axios.defaults.baseURL = 'http://127.0.0.1:9000' btns[0 ].onclick = () => { axios.get('/server' ,{ params : { id : 100 , vip : 7 }, header : { c : 300 , d : 400 }, }).then((value )=> { console .log(value) }) } </script > </body >
好处就是能将URL简化,也像jQuery一样操作
使用fetch函数发送请求 1 2 3 4 5 6 7 8 9 10 11 12 13 fetch('http://127.0.0.1:9000/server', { // 请求方法 method: 'POST', headers: { c: 300, d: 400 }, body: 'id=100&vip=7' }).then(response => { return response.json() }).then(response => { console.log(response) })
我们需要获取后台数据,就要使用then
我们可以发现在发送POST请求时会首先发送一个OPTION请求?
第八章 跨域 同源策略 同源策略最早是一种安全策略
同源:协议、域名、端口号三者必须保持一致
违背同源策略就会发生跨域
解决跨域问题 jsonp
jsonp是一个非官方的跨域解决方案,只支持get请求
jsonp的工作原理:页面一些 标签具有跨域能力:script,img,link,ifame。jsonp就是借助script
具体操作:服务端发送的是函数调用即可
1 2 3 4 5 6 7 app.all('/jsonp' , (request, response ) => { const data = { name : 'Once' } let FAQ = JSON .stringify(data) response.end(`handle(${FAQ} )` ) })
1 2 3 4 5 6 7 8 9 10 11 <body > <div id ="result" > </div > <script > handle = function (data ) { const result = document .getElementById('result' ) result.innerHTML = data.name } </script > <script src ="http://127.0.0.1:9000/jsonp" > </script > </body >
注意:在这里必须得是json格式,不然会报错的
下面是一个小案例:在文本框输入并让文本框变色,再取出服务器的数据渲染到html页面上
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 <script > const input = document .getElementById('input' ) const handle = (data ) => { input.style.border = "solid 1px red" const p = document .createElement('p' ) p.innerHTML = data.msg document .body.appendChild(p) } input.onblur = () => { let username = this .value const script = document .createElement('script' ) script.src = 'http://127.0.0.1:9000/UC1' document .body.appendChild(script) } </script >
1 2 3 4 5 6 7 app.all('/UC1' , (request, response ) => { const data = { msg : '用户名已经存在' } let str = JSON .stringify(data) response.end(`handle(${str} )` ) })
jQuery jQuery部分,活用的是callback
1 2 3 4 5 6 7 8 9 10 11 <script > $('button' ).eq(0 ).click(() => { $.getJSON('http://127.0.0.1:9000/jquery-server?callback=?' , (data ) => { $('#result' ).html(` 名称: ${data.name} , 地址: ${data.city} ` ) }) }) </script >
1 2 3 4 5 6 7 8 9 10 app.all('/jquery-server' , (request, response ) => { const data = { name : 'lkd' , city : ['北京' ,'上海' ,'深圳' ] } let str = JSON .stringify(data) let cb = request.query.callback response.end(`${cb} (${str} )` ) })
CORS CORS:跨域资源共享,为官方的解决方案
特点:不需要在客户端做任何特殊的操作,完全在服务器处理
工作原理:通过设置一个响应头来告诉浏览器,该请求允许跨域,浏览器收到该响应,以后就会对响应放行
1 2 3 4 5 response.setHeader('Access-Control-Allow-Origin' ,'*' ) response.setHeader("Access-Control-Allow-Headers" , "*" ) response.setHeader("Access-Control-Allow-Method" , "POST" )
Author:
BK201-Drama
License:
Copyright (c) 2019 CC-BY-NC-4.0 LICENSE
Slogan:
Do you believe in DESTINY ?