最终实现效果:
![](https://i-blog.csdnimg.cn/blog_migrate/194acefb4e733ba7359474d5747f4b2b.gif)
1.json-server插件准备json数据
data.json
{
"stu": [
{
"name": "cdd",
"age": "18",
"gender": "1",
"nation": "china"
}
]
}
2.封装xhr、fetch
//封装xhr
const xhrRequest = (options = {}) => {
const { url, method = "GET", onProgress, data = null } = options;
return new Promise((resolve) => {
//创建xhr对象
const xhr = new XMLHttpRequest();
//监听状态改变
xhr.addEventListener("readystatechange", () => {
if (xhr.readyState === xhr.DONE) {
resolve(xhr.responseText);
}
});
//下载监听进度
xhr.addEventListener("progress", (e) => {
//进度根据loaded和total的返回值进行动画显示
// console.log(e.loaded, e.total);
onProgress &&
onProgress({
loaded: e.loaded,
total: e.total,
});
});
//上传监听进度与下载类似
xhr.upload.addEventListener("progress", (e) => {});
//发起http请求
xhr.open(method, url);
xhr.send(data);
});
};
// 封装fetch
const fetchRequest = (options = {}) => {
const { url, method = "GET", onProgress, data = null } = options;
return new Promise(async (resolve) => {
const resp = await fetch(url, {
method,
body: data,
});
//下两行也可拿到响应文本吧
// const body = await resp.text();
// resolve(body);
//以下代码获取响应文本和loaded、total值
const total = +resp.headers.get("content-length");
const decoder = new TextDecoder();
let body = "";
const reader = resp.body.getReader();
let loaded = 0;
while (1) {
const { done, value } = await reader.read();
if (done) {
break;
}
loaded += value.length;
body += decoder.decode(value);
console.log(loaded, total);
console.log(loaded);
onProgress &&
onProgress({
loaded,
total,
});
}
resolve(body);
//fetch不支持上传监听进度,目前w3c正在讨论的一种方案:ServiceWorker->BackgroundFetchManager
});
};
export { xhrRequest, fetchRequest };
3.编写html页面和样式,并做逻辑处理
html
<!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>Document</title>
<link rel="stylesheet" href="./progress.css">
</head>
<body>
<div class="box">
<button>请求</button>
<div class="progress">
<div class="content">
<div class="text">0%</div>
<div class="outer">
<div class="inner">
</div>
</div>
</div>
</div>
</div>
<script type="module" src="./index.js"></script>
</body>
</html>
less
* {
margin: 0;
padding: 0;
}
.box {
width: 100%;
background: #c9c9c9;
display: flex;
height: 100vh;
justify-content: center;
align-items: center;
}
button {
margin: 50px auto;
width: 200px;
height: 50px;
background: rgb(54, 52, 52);
color: white;
font-size: 22px;
border-radius: 5px;
}
.progress {
display: none;
width: 300px;
height: 300px;
position: fixed;
background: rgb(213, 125, 216);
z-index: 2;
border-radius: 5px;
box-shadow: 1px 2px 5px rgba(0, 0, 0, 0.5);
.content {
width: 300px;
height: 300px;
display: flex;
flex-direction: column;
align-items: center;
justify-content: center;
.text {
color: #fff;
font-size: 46px;
}
.outer {
width: 80%;
height: 10%;
background: rgb(255, 255, 255);
border-radius: 10px;
.inner {
width: 0%;
height: 100%;
background: rgb(34, 165, 17);
box-sizing: border-box;
clip: rect(0, 50%, 100%, 0);
border-radius: 10px;
}
}
}
}
index.js
import { xhrRequest, fetchRequest } from "./requst.js";
const btn = document.querySelector("button");
const onProgress = (val) => {
console.log(val);
};
btn.addEventListener("click", async () => {
// const res = xhrRequest({ url: "http://localhost:3000/stu" });
const res = await fetchRequest({ url: "http://localhost:3000/stu", onProgress });
// console.log(res);
showProgress();
});
const doms = {
progress: document.querySelector(".progress"),
text: document.querySelector(".text"),
inner: document.querySelector(".inner"),
};
//展示进度条动画
const showProgress = () => {
doms.progress.style.display = "block";
doms.inner.style.transition = " all 0.5s";
controls(100231, 6000);
};
const controls = (total, speed) => {
let num = 0;
let rate = 0;
let timer = setInterval(() => {
if (num < total) {
num += speed;
let rates = Math.ceil((num / total).toFixed(2) * 100);
rate = rates < 100 ? rates : 100;
} else {
clearInterval(timer);
setTimeout(() => {
doms.progress.style.display = "none";
}, 1000);
}
doms.text.innerHTML = rate + "%";
doms.inner.style.width = rate + "%";
}, 300);
};