题目:点击页面按钮,调用两个API: api-a, api-b, 每个api返回10张图片,在页面上交叉显示20张图片: api1_img1, api2_img1, api1_img2, api2_img2, ... 思路:首先需要创建一个axios的实例,再通过axios去向接口发起请求,发起两个请求通过Promise.all来异步实现,将获取到的数据交叉放在一个数组里面,创建文档碎片,遍历数组将图片交叉渲染到页面。
@TOC
一、创建axios实例
代码如下:
//设置请求头
const headers = {
'Content-Type': 'application/json;charset=UTF-8'
}
//创建axios实例
const Axios = axios.create({
timeout: 30000,//超时时间
headers
})
二、用get方法发起请求
代码如下:
function fetchImg (url) {
return Axios.get(url)
}
二、通过Promise.all发起异步请求
Promise.all([fetchImg("api-a"), fetchImg("api-b")])
.then(res=>{})
.catch(error=>{})
.then是成功时的回调。.catch是捕获异常。
三、设置交叉合并数组的函数
// 交叉合并两个数组成一个数组,arr1和arr2分别为从api-a和api-b获取到的图片数组
function concatArray (arr1, arr2) {
if (!arr1.length && !arr2.length) return []
const arr = []
let p1 = 0, p2 = 0, count = 1
while (p1 < arr1.length || p2 < arr2.length) {
// count是奇数时
if (count % 2 != 0 && p1 < arr1.length) {
arr.push(arr1[p1])
p1++
count++
continue
}
// count是偶数时
if (count % 2 == 0 && p2 < arr2.length) {
arr.push(arr2[p2])
p2++
count++
}
}
return arr
}
四、在load函数内实现api调用并且获取交叉数组
function load () {
Promise.all([fetchImg("api-a"), fetchImg("api-b")])
.then(res => {
if (res) {
const url1 = res[0], url2 = res[1]
const urls = concatArray(url1, url2)
}
})
.catch(err => console.log(err))
}
五、接下来在load函数内创建文档碎片并渲染图片
function load () {
Promise.all([fetchImg("api-a"), fetchImg("api-b")])
.then(res => {
if (res) {
const url1 = res[0], url2 = res[1]
const urls = concatArray(url1, url2)
let oFragmeng = document.createDocumentFragment()
urls.forEach(url => {
let img = document.createElement('img');
img.src = url
oFragmeng.appendChild(img);
})
document.body.appendChild(oFragmeng)
}
})
.catch(err => console.log(err))
}
六、完整代码如下
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8" />
<title>Static Template</title>
</head>
<body>
<button type="button" onclick="load()">获取图片</button>
</body>
<script src="https://unpkg.com/axios@0.27.0/dist/axios.min.js"></script>
<script type="text/javascript">
const headers = {
// 表示后面的文档属于什么MIME类型
// application/json : JSON数据格式
// charset=”utf-8”是告知浏览器此页面属于什么字符编码格式
// unicode:万国码
// **utf-8:**unicode的升级版。
'Content-Type': 'application/json;charset=UTF-8'
}
const Axios = axios.create({
timeout: 30000,
headers
})
function load () {
Promise.all([fetchImg("api-a"), fetchImg("api-b")])
.then(res => {
if (res) {
const url1 = res[0], url2 = res[1]
const urls = concatArray(url1, url2)
let oFragmeng = document.createDocumentFragment()
urls.forEach(url => {
let img = document.createElement('img');
img.src = url
oFragmeng.appendChild(img);
})
document.body.appendChild(oFragmeng)
}
})
.catch(err => console.log(err))
}
function fetchImg (url) {
return Axios.get(url)
}
// 交叉合并两个数组成一个数组
function concatArray (arr1, arr2) {
if (!arr1.length && !arr2.length) return []
const arr = []
let p1 = 0, p2 = 0, count = 1
while (p1 < arr1.length || p2 < arr2.length) {
// count是奇数时
if (count % 2 != 0 && p1 < arr1.length) {
arr.push(arr1[p1])
p1++
count++
continue
}
// count是偶数时
if (count % 2 == 0 && p2 < arr2.length) {
arr.push(arr2[p2])
p2++
count++
}
}
return arr
}
</script>
</html>
七、文档碎片
createDocumentFragment()方法,是用来创建一个虚拟的节点对象,或者说,是用来创建文档碎片节点。它可以包含各种类型的节点,在创建之初是空的。 DocumentFragment节点不属于文档树,当请求把一个DocumentFragment节点插入文档树时,插入的不是DocumentFragment自身,而是它的所有子孙节点,即插入的是括号里的节点。也可以将DocumentFragment理解为一个占位符,暂时存放那些一次插入文档的节点。因此,当需要添加多个dom元素时,只需要将这些元素添加到DocumentFragment中,再统一将DocumentFragment添加到页面,会减少页面渲染dom的次数,效率会明显提升,这就是此处使用文档碎片的原因。