AJAX
复习
1.什么是ajax?
与服务器进行通讯的一种技术,能够实现同步或异步的局部刷新
2.ajax的核心对象是什么?
XMLHttpRequest 简称 xhr
3.同步与异步的区别?
同步:安装顺序一步一步执行
缺点:容易造成阻塞
异步:不按照顺序执行
确定:在js里要通过回调函解决,
在ajax里要使用onreadystatechange事件结合回调函数获取数据
event loop , 教室里有男,有女,女士优先,门确只有一条门
女士优先的进行排队,男生就排到男生队列里
onclick,onmouseenter.. onredaystatechange 宏任务
promise 微任务
get 请求和post请求?
get比post要快
post比get要相对安全
get是通过url地址传值,适合做查询
post 通过表单体传值,适合做提交
post比get请求的格式要多,post支持 文本,音频,视频等等..
get请求支持ascii或者字符,而且url地址的长度会被服务限制
get请求容易尝试缓存
post请求
<script>
function getParams(o) {
let str = "";
for (let key in o) {
str += key + "=" + o[key] + "&";
}
return str;
}
function createXHR() {
if (window.XMLHttpRequest) {
return new XMLHttpRequest()
}
return new ActiveXObject("Msxml2.XMLHTTP");
}
function ajax(url, data, callback) {
//ajax的5个步骤
//1.创建xhr核心对象
let xhr = createXHR();
//2.准备open参数
xhr.open("post", url)
//3.发送请求
//请求头
xhr.setRequestHeader("Content-Type",
"application/x-www-form-urlencoded");
xhr.send(getParams(data));
xhr.responseType = "json"; //返回数据,希望是json格式,
//就不需要转换了
//4.异步需要监听onreadystatechange事件
xhr.onreadystatechange = function () {
//5. 判断状态通过回调获取数据
if (xhr.status == 200 && xhr.readyState == 4) {
if (typeof (callback) == "function") {
callback(xhr.response);
}
}
}
}
// url地址 http://useker.cn/login
// 请求方式 post
// 参数 {uname:xxx,upwd:xxx}
// 返回值的模板 {msg,code,data};
//拿到表单,给表单绑定 submit事件,还需要阻止默认行为
var oForm = document.querySelector("form");
oForm.onsubmit = function () {
var oUser = {
uname: this.uname.value,
upwd: this.upwd.value
}
//result 结果
ajax("http://useker.cn/login", oUser, function (result) {
console.log(result);
let { msg, code, data } = result;
if (code === 1) {
//把当前登录成功,并且后端返回当前用户的信息,
//把该信息保存的本地存储
sessionStorage.setItem("userInfo", JSON.stringify(data));
}
})
return false;
}
</script>
图片上传
<body>
<img src="" alt="" id="pic">
<!-- multiple 可以多选图片 -->
<input type="file" value="图片预览" id="upload">
<input type="button" value="图片上传" id="send">
<script>
function createXHR() {
if (window.XMLHttpRequest) {
return new XMLHttpRequest()
}
return new ActiveXObject('Msxml2.XMLHTTP');//IE6
}
function ajax(url, data, callback) {
let xhr = createXHR();
xhr.open("post", url);
xhr.send(data);
xhr.responseType="json";
xhr.onreadystatechange = function () {
if (xhr.status == 200 & xhr.readyState == 4) {
console.log(xhr.response);
}
}
}
</script>
<script>
var oPic = document.querySelector("#pic");
var oUpload = document.querySelector("#upload");
//图片上传是绑定change事件
//默认只能选择一张
oUpload.onchange = function () {
console.dir(this.files[0]);
var file = new FileReader();//文件读取器,u盘
file.readAsDataURL(this.files[0]);//把文件拷贝到U盘里
file.onload = function () {//读取完成,就触发laod事件
//result 结果
//Base64是网络上最常见的用于传输8Bit字节码的编码方式之一,
//Base64就是一种基于64个可打印字符来表示二进制数据的方法
//把u盘里结果 赋给 img标签
//
console.log(file.result);
oPic.src = file.result;
}
}
//点击按钮上传
var oSend = document.querySelector("#send");
oSend.onclick = function () {
//fromData 支持文本与文件
var data = new FormData();
data.append("aaa",oUpload.files[0]);//
ajax("http://useker.cn/upload",data,function (res) {
console.log(res);
})
}
</script>
</body>
jq方法post请求
<script>
var oForm = document.querySelector('form');
oForm.onsubmit = function () {
var oUser = {
uname: this.uname.value,
upwd: this.upwd.value
}
// $.ajax 默认是get请求
$.ajax({
url: "http://useker.cn/login",//请求路径
type: "post",//请求方式
data: oUser,//向服务器发送的参数
async:true, // 异步 false:同步
beforeSend() {//发送之前执行的函数
document.querySelector("img").style.display="block";
},
// dataType: "json",//返回的数据格式json
success(res) {//成功的回调函数
console.log(res);
document.querySelector("img").style.display="none";
}
})
return false;
}
</script>
自行封装 jq post请求
const $ = (function () {
//处理参数的
const getParams = (o) => {
var str = "";
for (let key in o) {
str += key + "=" + o[key] + "&"
}
return str;
}
//创建ajax的核心对象
const createXHR = () => {
if (window.XMLHttpRequest) {
return new XMLHttpRequest()
}
return new ActiveXObject("Msxml2.XMLHTTP");
}
//url:请求的地址
//type:请求的方式,默认是get
//async:同步或异步,默认是异步
//data:向服务器发送的数据
//dataType: 返回的数据格式,默认是json
//success:成功的回调函数
//beforeSend:ajax发送之前的回调函数
const ajax = (settings = {}) => {
var settings = Object.assign({
type: "get", //默认get请求
async: true,//默认异步
dataType: "json",//默认返回的json数据
contentType: "application/x-www-form-urlencoded; charset=UTF-8",
processData: true, //如果是true,就把data从对象转化成字符串
}, settings);
if (settings.data && settings.processData && typeof (settings.data) !== "string") {
//转化成字符串后,覆盖原来的对象
settings.data = getParams(settings.data);
}
//1.创建xhr的核对象
let xhr = createXHR();
//添加一个发送之前的函数
if (typeof (settings.beforeSend) == "function") {
settings.beforeSend()
}
//2.准备参数
if (settings.type.toLowerCase() == "get") {
xhr.open(settings.type, settings.url + "?" + settings.data, settings.async);
//3.发送
xhr.send(null);
} else if (settings.type.toLowerCase() == "post") {
xhr.open(settings.type, settings.url, settings.async);
//发送之前,配置表单 默认是支持表格格式
if (settings.contentType) {
xhr.setRequestHeader('Content-Type', settings.contentType);
}
//3.发送
xhr.send(settings.data);
}
xhr.responseType = settings.dataType;//返回的json数据
//4.获取结果
if (settings.async == true) {//异步
xhr.addEventListener("readystatechange", function () {
if (xhr.readyState == 4) {
getResult();
}
})
} else {//同步
getResult()
}
//内部函数
function getResult() {
if (xhr.status == 200) {
if (typeof (settings.success) == "function") {
settings.success(xhr.response);
}
}
}
}
//把这个ajax暴露出现, 这里是一个自执行函数,自执行函数内部的ajax方法,
//不能被外部指向访问,通过retrun 暴露出去,外面就可以访问ajax方法
return {
ajax
}
})()
用自行封装的jq代码 进行post请求
var oForm = document.querySelector('form');
oForm.onsubmit = function () {
var oUser = {
uname: this.uname.value,
upwd: this.upwd.value
}
// $.ajax 默认是get请求
$.ajax({
url: "http://useker.cn/login",//请求路径
type: "post",//请求方式
data: oUser,//向服务器发送的参数
async: true, // 异步 false:同步
beforeSend() {//发送之前执行的函数
document.querySelector("img").style.display = "block";
},
// dataType: "json",//返回的数据格式json
success(res) {//成功的回调函数
console.log(res);
document.querySelector("img").style.display = "none";
}
})
return false;
}
同源策略
同源策略 是ajax的一种安全机制
同源:
3个必须统一
协议,域名,端口
http://www.baidu.com
https://www.baidu.com //协议不同
http://baidu.com 一级域名
http://mail.baidu.com 二级域名
http://aaa.bbb.baidu.com 三级域名 域名不同
http://useker.cn:80
http://useker.cn:5500 端口不一致
Access-Control-Allow-Origin 跨域 cors
1.是否允许跨域 后端程序员,在响应头里设置
Access-control-allow-origin:* //* 任意网站
2.使用非官方的跨域解决方案 JSONP
原理: 它并不是真正的ajax技术,它是利用
一些带有src属性的标签,可以不受限制的访问
外部资源,接口callback回调函数获取数据
jsonp,它是其实是一种get请求,适合做查询
3.服务器代理 proxy server
$.ajax({
url: "http://useker.cn"
})
jsonp的封装
const $ = (function () {
const getParams = (o) => {
var str = "";
for (let key in o) {
str += key + "=" + o[key] + "&";
}
return str;
}
const JSONP = (settings = {}) => {
//1.先定义函数 (函数名随机) jquery_1333
// 如果jsonpCallback有值,就取自己,否则就随机函数名称
let fnName = settings.jsonpCallback ? settings.jsonpCallback : ("jquery_" + parseInt(Math.random() * 10000));
//window['jquery_1333']
window[fnName] = settings.success;
//2.
//http://www.baidu.com/xxxx?wd=niaho&cb=jquery_1333
let newStr = settings.url + "?" + getParams(settings.data) + settings.jsonp + "=" + fnName;
//3.动态创建script标签
var oScript = document.createElement("script");
oScript.src = newStr;
document.body.appendChild(oScript);
//4.script用完了,就的删除
//凡事带有src属性的,都会有一个 onload事件
oScript.onload = function () {
this.remove();
}
}
return {
JSONP
}
})()
// JSONP({
// url:"http://www.baidu.com/", //
// data:{wd:"niaho"},// --> wd=niaho
// jsonp:"cb",//百度,豆瓣 callback
// jsonpCallback: 'fn',//自己定义函数,
// success: function (res) {
// }
// })
json相关的案例
<script>
//JSONP
// 利用带有src属性的标签去访问外部资源
// 结合callback拿到数据
//1. 它并不是官方跨域方案
//2. 它不是真正的ajax
//3. 它只适合get请求,查询
//豆瓣 callback
//https://sp0.baidu.com/5a1Fazu8AA54nxGko9WTAnF6hhy/su?wd=nihao&cb=fn
//url = https://sp0.baidu.com/5a1Fazu8AA54nxGko9WTAnF6hhy/su
// data = wd=nihao&cb=fn
$.JSONP({
url:"https://sp0.baidu.com/5a1Fazu8AA54nxGko9WTAnF6hhy/su",
data:{wd:'你好'},
jsonp:"fn",
success(res){
console.log(res);
}
})
</script>
<script>
//https://sp0.baidu.com/5a1Fazu8AA54nxGko9WTAnF6hhy/su?wd=miqi&cb=fn
var oBtn = document.querySelector("#btn");
var oTxt = document.querySelector('#txt');
oBtn.onclick = function () {
$.JSONP({
url: "https://sp0.baidu.com/5a1Fazu8AA54nxGko9WTAnF6hhy/su",
data: {
wd: oTxt.value
},
jsonp: "cb",
success(res) {
console.log(res);
}
})
}
</script>