Ajax入门
// 创建ajax对象
var xhr = new XMLHttpRequest()
// get请求和其传参方式
var params = 'usename=xiaoming&age=22'
xhr.open('get','http://localhost:3000/get?'+params)
xhr.send()
// post请求和其传参方式
var params = 'usename=xiaoming&age=22'
// 下一章(Post请求参数的格式),讲解了如何设置请求头的Content-Type的属性值
xhr.setRequestHeader('Content-Type','application/x-www-form-urlencoded')
xhr.open('post','http://localhost:3000/post?')
xhr.send(params)
xhr.onload = function(){
console.log(xhr.responseText)
}
在http请求与响应中,无论是请求参数还是响应内容,如果事对象类型,最终都会转换为字符串进行传输
post请求参数的格式
- application/x-www-form-urlencoded
name=xiaoming&age=22
- application/json
{ name:'xiaoming',age:'22' } // 需要用JSON.stringify转成字符串格式
- formData格式
详见下文
HTTP状态码
简要介绍
1、400 网络畅通,服务端能接收到请求服务器返回的数据不是预期的结果
2、404网络畅通,服务器没有接收到请求,返回到404状态码
3、500 网络畅通,服务器端能接受到请求,服务器端发生错误
4、网络中断。请求无法发送请求服务器
xhr.status // 获取状态码
xhr.onerror = function(){
alert('网络中断,无法发送ajax请求')
}
课外练习 : 封装ajax函数
FormData
作用:
- 模拟HTML表单,相当于将HTML表单映射成表单对象,自动将对象中的数据拼接成请求参数的格式
- 异步上传二进制文件
- 可以实现图文上传
<!-- 1.准备HTML表单 -->
<form id='form'>
<input type='text' name='username'>
<input type='password' name='password'>
<input type='button' />
</form>
<script>
// 2.将HTML表单转化为formData对象
var form = document.getElementId('form')
var formData = new FormData(form)
// FormData对象实例的方法
formData.get('username')
formData.set('key','value')
formData.delete('username')
formData.append('key','value')
// 3.发送给后端 post请求方式
xhr.send(formData)
</script>
二进制文件上传
<input type=''file' id='file' />
<script>
var file = document.getElementById('file')
file.onchange = function(){
var formData = new FormData()
formData.append('attrName',this.file[0])
xhr.open('post','www.example.com')
xhr.send(formData)
}
</script>
FormData文件上传进度的展示
var file = document.getElementById('file')
file.onchange = function(){
var formData = new FormData()
formData.append('attrName',this.file[0])
xhr.open('post','www.example.com')
// 文件上传过程中持续出发onprogress事件
xhr.upload.onprogress = function(ev){
// 当前上传文件大小/文件总大小 再将结果转换为百分数
bar.style.width = (ev.loaded / ev.total) * 100 + '%'
}
xhr.send(formData)
}
FormData文件上传图片即时预览
-
可以通过H5中的fileReader对象来做 ,Blob对象实现文件下载和图片预览 FileReader
缺点:H5比较新,兼容性差 -
或者可以使用如下这种方式,通过后端返回的url进行预览
// 接上面的代码
xhr.onlaod = funcction () {
if(xhr.status == 200){
var result = JSON.parase(xhr.responseText)
// 动态创建img比获取img标签的方式效果要好一些
var img = document.createElement('img')
img.src = result.path
img.onload = function(){
box.appendChild(img)
}
}
}
Ajax的请求限制
就一个限制 ----> 跨域问题
产生跨域的原因 :同源策略
跨域的解决方式 :JSONP、服务器代理、CORS
同源策略
同源策略是浏览器的一种安全策略,所谓同源是指域名、协议、端口完全相同
只有同源的地址才可以互相通过Ajax的方式请求
同源或者不同源说的是两个地址之间的关系,不同源地址之间请求我们称之为跨域请求
什么是同源?例如:http://www.example.com/detail.html与以下地址对比
对比地址 | 是否同源 | 原因 |
---|---|---|
http://api.example.com/detail.html | 不同源 | 域名不同 |
https://www.example.com/detail.html | 不同源 | 协议不同 |
http://www.example.com:8080/detail.html | 不同源 | 端口不同 |
http://api.example.com:8080/detail.html | 不同源 | 域名、端口不同 |
https://api.example.com/detail.html | 不同源 | 协议、域名不同 |
https://www.example.com:8080/detail.html | 不同源 | 端口、协议不同 |
http://www.example.com/other.html | 同源 | 只是目录不同 |
JSONP
jsonp是json with padding的缩写,它不属于Ajax请求,但它可以模拟Ajax请求
- 将不同的源的服务器请求地址写在script标签的src属性中
<script>
function fn(params){
console.log(params)
}
var btn = document.getElementById('btn')
btn.onClick = function() {
var srcipt = document.createElement('script')
script.src = 'http://loacalhost:3001/better?callback=fn'
document.body.appendChild(script)
script.onload = function(script){
// 请求完成后,将script标签删除掉
document.body.removeChild(script)
}
}
</script>
- 服务器端响应数据必须是一个函数的调用,真正要发送给后端的数据需要函数调用的参数
// node获取参数值fn
const data = 'fn({name:"张三",age:"20"})'
// 后端响应
res.send(data)
JSONP的封装
function jsonp (url, params, callback) {
var funcName = 'jsonp_' + Date.now() + Math.random().toString().substr(2, 5)
if (typeof params === 'object') {
var tempArr = []
for (var key in params) {
var value = params[key]
tempArr.push(key + '=' + value)
}
params = tempArr.join('&')
}
var script = document.createElement('script')
script.src = url + '?' + params + '&callback=' + funcName
document.body.appendChild(script)
window[funcName] = function (data) {
callback(data)
delete window[funcName]
document.body.removeChild(script)
}
}
jsonp('http://localhost/jsonp/server.php', { id: 123 }, function (res) {
console.log(res)
})
jsonp('http://localhost/jsonp/server.php', { id: 123 }, function (res) {
console.log(res)
})
服务器代理
服务器和服务器间是没有同源策略的,我们可以利用没有同源策略的1号服务器去访问有同源策略的2号服务器,然后让1号服务器,发给我们客户端
CORS(跨域资源共享)
由后端设置响应头
// 1.允许哪些客户端访问我
// * 代表允许所有的客户端访问我
// 注意:如果跨域请求中涉及到cookie信息传递,值不可为 * 号
res.header("Access-Control-Allow-Origin","*")
只是在被请求的服务端响应的时候添加一个Access-Control-Allow-Origin的响应头,表示这个资源允许指定的跨域请求。
withCredentials属性
在使用Ajax技术发送跨域请求时,默认情况下不会在请求中携带cookie信息
withCredentials:指定在涉及请求时,是否携带cookie信息,默认值为false (前端设置)
Access-Control-Allow-Credentials:true允许客户端发送请求时携带cookie (后端设置)
xhr.withCredentials = true
后端设置如下代码
res.header("Access-Control-Allow-Credentials",true)