一、ajax
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title>ajax</title>
</head>
<body></body>
</html>
<script type="text/javascript">
/*
ajax:ajax异步的javascript和XML,ajax其实就是浏览器与服务器之间的一种异步通信方式,可以在无需加载(刷新)整个网页的情况下,更新部分网页数据的技术。
通俗理解:ajax就是在网页中利用XMLHttpRequest对象和服务器进行数据交互的方式
什么是异步什么是同步?
异步:执行完函数或者方法后,不必等待返回值或消息,就可以直接执行下一个命令,无需等待
同步:执行完一个函数或者方法后,一直等待系统返回值或者消息,只有接收到返回的值或者消息时,才继续往下执行其他命令,需要等待。
XML:是前后端数据通信时传输数据的一种格式
网页中的数据是从服务器获取的,那么前端如何拿到数据渲染到页面?
通过ajax向服务器发送请求,并从服务器接收响应数据
后端怎么知道前端需要什么数据?
在进行ajax请求时,通过传递不同的参数,来告诉后端我需要什么类型的数据
*/
</script>
二、ajax基本语法
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title>ajax基本语法</title>
</head>
<body></body>
</html>
<script type="text/javascript">
/*
创建ajax的步骤:
1.创建一个XMLHttpRequest对象,也就是创建一个异步调用对象
2.创建一个新的http请求,并且指定请求方式(建立连接)
3.发送http请求
4.设置响应http请求状态变化的函数
5.获取返回的数据
6.使用js和dom实现页面的局部数据刷新
http:是一种用于在网络上传输超文本数据的协议,它是一种客户端-服务器协议,用于在客户端和服务器之间通信。
http的三次握手?
1.客户端向浏览器发送请求
2.服务器接收到请求,需要进行核对操作,如果接收到了,就向客户端返回接收到的请求信息,告诉它你能接收到。
3.客户端拿着服务器返回成功接收到的这个信息再去向服务器请求,两者才能建立连接。
*/
// ----------第一步:创建ajax对象,也就是创建一个异步调用对象
var xhr = new XMLHttpRequest();
// ----------第二步:创建http请求
/*
常见的请求方式:get post del put
创建http请求:
xhr.open(参数1,参数2,参数3)
参数1:请求方式(后端接口文档提供的)
参数2:接口地址(后端接口文档提供的)
参数3:同步/异步 默认是true异步
*/
// get请求 参数要在接口地址后面拼接
xhr.open("get", "接口地址?userName=123&age=18", true);
// post请求 参数要在发送请求的时候拼接 不在创建http请求中拼接
xhr.open("post", "接口地址", true);
// 如果是post请求,需要添加请求头,不同的请求头,请求的数据格式不一样
// post请求设置请求头
/*
Content-Type:执行请求的数据类型
Content-Type常用的类型:
application/json:请求或响应主体数据是json格式
multipart/from-data:请求主体数据是表单数据,常用语文件上传等操作
application/x-www-form-urlencoded:最常见的post提交数据的方式,在数据发送中会把数据处理成uesrName=123&age=14的格式
*/
xhr.setRequestHeader("Content-Type", "application/x-form-urlencoded");
// ----------第三步:发送http请求
// get方法
xhr.send();
// post方法
xhr.open("userName=123&age=18");
// ----------第四步:设置监听请求变化的函数
xhr.onreadystatechange = function () {
// readystate 请求状态
// 0 调用open方法之前
// 1 调用send方法之前
// 2 send方法已完成,已经接收到所有的相关内容
// 3 解析接收到的数据
// 4 解析完成(数据能使用)
if (xhr.readyState === 4) {
// 服务器状态 状态码status 200 成功
if (xhr.status === 200) {
// ----------第五步:获取返回的数据
var obj = JSON.parse(xhr.responseText);
// ----------第六步:实现局部数据刷新(渲染数据)
} else {
// 请求失败
}
}
};
/*
get和post请求的区别?
1.安全性问题
get请求参数会拼接到接口地址上,参数会暴露
post请求参数不可见
2.数据传输量
get有长度限制
post没有长度限制
3.缓存问题
get数据会被缓存下来
post不会
4.一般情况下,增删改使用post请求 查使用get
*/
/*
常见的状态码:
*200 请求成功
301 资源被永久转移到了其他url
*400 客户端请求语法错误
401 发送请求需要被认证
*403 代表请求的资源被服务器拒绝
*404 代表表面的服务器无法找到指定的资源
*500 服务器在执行请求时发生了错误
*502 服务器网关出现了错误
503 服务器当前处于停机维护 现在无法处理请求
*/
</script>
三、get请求练习1.0
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title>get请求练习</title>
</head>
<body>
<div class="box"></div>
</body>
</html>
<script type="text/javascript">
// 创建ajax对象
var xhr = new XMLHttpRequest();
// 创建http请求 指定请求方式
xhr.open("get", "网络地址");
// 发送请求
xhr.send();
// 设置监听请求变化的函数
xhr.onreadystatechange = function () {
// 数据已经解析完成 并且接口调通
if (xhr.readyState === 4 && xhr.status === 200) {
console.log(xhr.responseText);
var box = document.querySelector(".box");
// 将接口返回的数据输出到页面上
box.innerHTML = xhr.responseText;
}
};
</script>
四、get请求练习2.0w
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title>get请求练习</title>
<style type="text/css">
.box {
text-align: center;
}
img {
width: 200px;
}
</style>
</head>
<body>
<div class="box"></div>
</body>
</html>
<script type="text/javascript">
// 创建ajax对象
var xhr = new XMLHttpRequest();
// 创建http请求
xhr.open("get", "网络地址");
// 发送请求
xhr.send();
// 设置监听请求变化的函数
xhr.onreadystatechange = function () {
// 当数据已经解析完成,并且接口调通
if (xhr.readyState === 4 && xhr.status === 200) {
console.log(JSON.parse(xhr.responseText));
var box = document.querySelector(".box");
var img = document.createElement("img");
img.src = JSON.parse(xhr.responseText).data;
box.appendChild(img);
}
};
</script>
五、post请求练习
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title>post请求练习</title>
<style type="text/css">
.box {
text-align: center;
}
img {
width: 300px;
}
</style>
</head>
<body>
<div class="box"></div>
</body>
</html>
<script type="text/javascript">
// 创建ajax对象
var xhr = new XMLHttpRequest();
// 建立请求
xhr.open("post", "网络地址");
// 设置请求头 post请求需要设置请求头
xhr.setRequestHeader("Content-Type", "application/x-www-form-urlencoded");
// 发送请求 post请求方法 传递的参数在发送请求中拼接
xhr.send("format=json");
// 设置监听函数
xhr.onreadystatechange = function () {
if (xhr.readyState === 4 && xhr.status === 200) {
console.log(JSON.parse(xhr.responseText));
var obj = JSON.parse(xhr.responseText);
var box = document.querySelector(".box");
box.innerHTML = `
<h3>${obj.data.name}</h3>
<img src="${obj.data.avatarurl}">
<br>
<dov class="content">${obj.data.content}</dov>
`;
}
};
</script>
六、处理传参格式
<script type="text/javascript">
/*
往函数中传一个对象:
{
tel:12345,
pwd:234
}
*/
function queryString(obj) {
console.log(obj);
var str = "";
for (var i in obj) {
console.log(i); // 属性
console.log(obj[i]); // 属性值
// 属性=属性值&属性=属性值
str += i + "=" + obj[i] + "&";
}
return str.substring(0, str.length - 1);
}
var a = queryString({
tel: 12345,
pwd: 234,
});
console.log(a);
</script>
七、ajax封装
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8" />
<title>ajax封装</title>
<style type="text/css">
img {
width: 50px;
}
</style>
</head>
<body>
<input type="text" name="" value="赤峰" id="ipt" />
<button class="btn">获取天气</button>
<p class="p1"></p>
<p class="p2"></p>
<img src="" />
</body>
</html>
<script src="ajax.js"></script>
<script type="text/javascript">
//获取input框
var ipt = document.querySelector("#ipt");
// 获取按钮
var btn = document.querySelector("button");
// 给按钮添加点击事件
// 获取城市的name和id
btn.onclick = function () {
// 调用ajax这个函数 传递参数
ajax({
// 请求方式
method: "get",
// 接口地址
url: "【和风天气api】",
// 传递参数
data: {
location: ipt.value,
key: "【和风天气key】",
},
// 请求头信息
contentType: "application/x-www-form-urlencoded",
// 同步异步
aysn: true,
// 成功的回调
success: function (res) {
console.log("成功", JSON.parse(res));
var obj = JSON.parse(res);
var p1 = document.querySelector(".p1");
p1.innerText = obj.location[0].name;
getWeather(obj.location[0].id);
},
// 失败的回调
error: function (res) {},
});
};
function getWeather(id) {
ajax({
// 请求方式
method: "get",
// 接口地址
url: "【和风天气api】",
data: {
location: id,
key: "【和风天气key】",
},
// 请求头(不需要)
// 同步异步
aysn: true,
// 成功的回调
success: function (res) {
console.log("成功", JSON.parse(res));
var arr = JSON.parse(res);
var p2 = document.querySelector(".p2");
p2.innerText = arr.now.temp + "℃" + "-" + arr.now.text;
var img = document.querySelector("img");
img.src = `QWeather-Icons-1.5.0/icons/${arr.now.icon}.svg`;
},
});
}
</script>
// 不确定的值
/*
请求方式 method
接口地址 url
传递参数 data
请求头信息 contentType
同步/异步 aysn
成功 success
失败 error
*/
// 以对象的形式接收传进来的参数,形参必须要以对象的属性一致
function ajax({ method, url, data, contentType, aysn, success, error }) {
console.log(method, url, data, contentType, aysn, success, error);
// 创建ajax对象
var xhr = new XMLHttpRequest();
// 处理参数 将传进来的参数对象处理成字符串拼接的形式
data = handleParam(data);
// console.log(data)
// 判断参数不为空 并且是get请求的话,我要把参数拼接到url后面
// data.length = 0的话是false
if (method == "get" && data.length) {
url += "?" + data;
}
// 创建请求 指定请求方式
xhr.open(method, url, aysn);
// 如果有请求头 需要设置请求头
if (contentType) {
xhr.setRequestHeader("Content-type", contentType);
}
// 发送请求
// 如果是get请求的话 直接发送请求 如果是post 需要在发送请求时拼接参数
if (method == "get") {
xhr.send();
} else {
xhr.send(data);
}
// 设置监听函数
xhr.onreadystatechange = function () {
if (xhr.readyState === 4 && xhr.status === 200) {
// 接口调通
if (success) {
//调用成功的回调 把接口返回的数据传过去
success(xhr.responseText);
}
} else {
// 请求失败
if (error) {
error(xhr.responseText);
}
}
};
}
// 处理传参格式
function handleParam(obj) {
var str = "";
for (var i in obj) {
// 属性=属性值&属性=属性值
str += i + "=" + obj[i] + "&";
}
return str.substring(0, str.length - 1);
}
八、防抖和节流
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title>防抖和节流</title>
</head>
<body>
<button>防抖</button>
</body>
</html>
<script src="ajax.js"></script>
<script>
/*
什么是防抖?什么是节流?
防抖:用于在事件触发后延迟执行回调函数。当一个事件被触发时,防抖会等待一段时间,如果在等待时间内没有再次触发该事件,那么再去执行回调函数。如果在等待时间内,再次触发了该事件,那么会重新开始计时。
说白了就是让多次执行变为最后一次执行。
节流:节流用于限制事件的触发频率。当一个事件触发后,节流会在一定的时间间隔内执行回调函数,并且在该事件间隔内,不会再次触发回调函数。
说白了就是让多次执行变为每隔一段时间执行。
*/
var btn = document.querySelector("button");
// 防抖
var timer = null;
btn.onclick = function () {
clearTimeout(timer);
timer = setTimeout(city, 1000);
};
function city() {
ajax({
method: "get",
url: "【和风天气api】",
data: {
location: "赤峰",
key: "【和风天气key】",
},
aysn: true,
success: function (res) {
console.log(JSON.parse(res));
},
});
}
// 节流
function fn(delay, behavior) {
var timer = null;
return function (val) {
if (!timer) {
timer = setTimeout(function () {
behavior(val);
timer = null;
}, delay);
}
};
}
function handlePrint(val) {
console.log(val, "我是鼠标坐标");
}
var handle = fn(3000, handlePrint);
document.addEventListener("mousemove", function (e) {
handle(e.offsetX);
});
</script>
// 不确定的值
/*
请求方式 method
接口地址 url
传递参数 data
请求头信息 contentType
同步/异步 aysn
成功 success
失败 error
*/
// 以对象的形式接收传进来的参数,形参必须要以对象的属性一致
function ajax({ method, url, data, contentType, aysn, success, error }) {
console.log(method, url, data, contentType, aysn, success, error);
// 创建ajax对象
var xhr = new XMLHttpRequest();
// 处理参数 将传进来的参数对象处理成字符串拼接的形式
data = handleParam(data);
// console.log(data)
// 判断参数不为空 并且是get请求的话,我要把参数拼接到url后面
// data.length = 0的话是false
if (method == "get" && data.length) {
url += "?" + data;
}
// 创建请求 指定请求方式
xhr.open(method, url, aysn);
// 如果有请求头 需要设置请求头
if (contentType) {
xhr.setRequestHeader("Content-type", contentType);
}
// 发送请求
// 如果是get请求的话 直接发送请求 如果是post 需要在发送请求时拼接参数
if (method == "get") {
xhr.send();
} else {
xhr.send(data);
}
// 设置监听函数
xhr.onreadystatechange = function () {
if (xhr.readyState === 4 && xhr.status === 200) {
// 接口调通
if (success) {
//调用成功的回调 把接口返回的数据传过去
success(xhr.responseText);
}
} else {
// 请求失败
if (error) {
error(xhr.responseText);
}
}
};
}
// 处理传参格式
function handleParam(obj) {
var str = "";
for (var i in obj) {
// 属性=属性值&属性=属性值
str += i + "=" + obj[i] + "&";
}
return str.substring(0, str.length - 1);
}
九、分页
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title>分页</title>
<style>
.paging p {
float: left;
border: 1px solid #ccc;
padding: 5px 8px;
cursor: pointer;
}
.paging .pagingIndex {
float: left;
margin-top: 16px;
}
.paging .pagingIndex span {
vertical-align: middle;
display: inline-block;
width: 30px;
height: 31px;
text-align: center;
line-height: 31px;
border: 1px solid #ccc;
cursor: pointer;
}
.paging .pagingIndex span.active {
background: blue;
color: #fff;
border-color: blue;
}
</style>
</head>
<body>
<div class="paging">
<p class="left">上一页</p>
<div class="pagingIndex">
<!-- <span class="active">1</span>
<span>2</span>
<span>3</span> -->
</div>
<p class="right">下一页</p>
</div>
</body>
</html>
<script type="text/javascript">
// 定义页码
var pages = 5;
// 获取盒子
var pagingIndex = document.querySelector(".pagingIndex");
// 获取上一页
var oLeft = document.querySelector(".left");
// 获取下一页
var oRight = document.querySelector(".right");
// 定义一个全局变量index
var index = null;
// 循环遍历页数
for (var i = 0; i < pages; i++) {
// 把页码输出到页面上
pagingIndex.innerHTML += `
<span>${i + 1}</span>
`;
// 获取所有生成的span 给第一个span添加active类名
var oSpan = document.querySelectorAll(".pagingIndex span");
oSpan[0].classList = "active";
// 给每一个span按钮添加点击事件
for (var j = 0; j < oSpan.length; j++) {
oSpan[j].onclick = function () {
// 把所有span的active类名清空
for (var k = 0; k < oSpan.length; k++) {
oSpan[k].classList = "";
}
// 只给当前点击的span添加类名
this.className = "active";
index = this.innerText;
console.log(index);
};
}
}
// 上一页按钮
oLeft.onclick = function () {
// 获取当前具有active类名的span标签
var spanAcitve = document.querySelector(".pagingIndex span.active");
// 获取当前具有active类名的span标签的上一个兄弟节点
console.log(spanAcitve.previousElementSibling);
// 如果上一个兄弟节点为空的话 弹出提示
if (spanAcitve.previousElementSibling == null) {
alert("到头了!");
} else {
spanAcitve.previousElementSibling.onclick();
}
};
// 下一页按钮
oRight.onclick = function () {
// 获取当前具有active类名的span标签
var spanAcitve = document.querySelector(".pagingIndex span.active");
// 获取当前具有active类名的span标签的上一个兄弟节点
console.log(spanAcitve.nextElementSibling);
// 如果下一个兄弟节点为空的话 弹出提示
if (spanAcitve.nextElementSibling == null) {
alert("到尾了!");
} else {
spanAcitve.nextElementSibling.onclick();
}
};
</script>
十、分页封装
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title>Document</title>
<style>
.paging p {
float: left;
border: 1px solid #ccc;
padding: 5px 8px;
cursor: pointer;
}
.paging .pagingIndex {
float: left;
margin-top: 16px;
}
.paging .pagingIndex span {
vertical-align: middle;
display: inline-block;
width: 30px;
height: 31px;
text-align: center;
line-height: 31px;
border: 1px solid #ccc;
cursor: pointer;
}
.paging .pagingIndex span.active {
background: blue;
color: #fff;
border-color: blue;
}
</style>
</head>
<body>
<div class="box1">
<div class="paging">
<p class="left">上一页</p>
<div class="pagingIndex">
<!-- <span class="active">1</span>
<span>2</span>
<span>3</span> -->
</div>
<p class="right">下一页</p>
</div>
</div>
</body>
</html>
<script src="page.js"></script>
<script type="text/javascript">
// 第一个参数:存放页码的盒子
// 第二个参数:上一页按钮
// 第三个参数:下一页按钮
// 第四个参数:页码数
// 第五个参数:回调函数
handlePaging(
".box1 .pagingIndex",
".box1 .left",
".box1 .right",
6,
function (index) {
console.log("接收到的参数", index);
}
);
</script>
function handlePaging(pagingIndex, pre, next, num, fn) {
// 定义页码
var pages = num;
// 获取盒子
var box = document.querySelector(pagingIndex);
// 获取上一页
var oLeft = document.querySelector(pre);
// 获取下一页
var oRight = document.querySelector(next);
// 定义一个全局变量index
var index = null;
// 循环遍历页数
for (var i = 0; i < pages; i++) {
// 把页码输出到页面上
box.innerHTML += `
<span>${i + 1}</span>
`;
// 获取所有生成的span 给第一个span添加active类名
// var oSpan = document.querySelectorAll('.pagingIndex span')
var oSpan = box.children;
oSpan[0].classList = "active";
// 给每一个span按钮添加点击事件
for (var j = 0; j < oSpan.length; j++) {
oSpan[j].onclick = function () {
// 把所有span的active类名清空
for (var k = 0; k < oSpan.length; k++) {
oSpan[k].classList = "";
}
// 只给当前点击的span添加类名
this.className = "active";
index = this.innerText;
console.log(index);
fn(index);
};
}
}
// 上一页按钮
oLeft.onclick = function () {
// 获取当前具有active类名的span标签
var spanAcitve = document.querySelector(`${pagingIndex} span.active`);
// 获取当前具有active类名的span标签的上一个兄弟节点
console.log(spanAcitve.previousElementSibling);
// 如果上一个兄弟节点为空的话 弹出提示
if (spanAcitve.previousElementSibling == null) {
alert("到头了!");
} else {
spanAcitve.previousElementSibling.onclick();
}
};
// 下一页按钮
oRight.onclick = function () {
// 获取当前具有active类名的span标签
var spanAcitve = document.querySelector(`${pagingIndex} span.active`);
// 获取当前具有active类名的span标签的上一个兄弟节点
console.log(spanAcitve.nextElementSibling);
// 如果下一个兄弟节点为空的话 弹出提示
if (spanAcitve.nextElementSibling == null) {
alert("到尾了!");
} else {
spanAcitve.nextElementSibling.onclick();
}
};
}