课程名称:await 函数用法
课程章节:二级菜单
课程讲师: Alex
课程内容:
二级菜单
先发送Ajax请求获取主菜单,鼠标在主菜单每一项会发送新的请求来获取子菜单,显示二级菜单。发送完请求,不再二次发送请求

HTML结构如下:
<ul id="menu" class="menu"> <li class="menu-item" data-key="hot" data-done="done"> <span>热门出发地</span> <div class="menu-content"> <img class="menu-loading" src="./loading.gif" alt="加载中" /> <p>内地热门城市</p> <p>热门景点</p> </div> </li> </ul>
二级菜单里默认情况是加载中的小图标,但获取到内容时,把小图标去掉显示内容


接下来,我们用js动态生成<li>标签里的内容
接口:
// https://www.imooc.com/api/mall-PC/index/menu // https://www.imooc.com/api/mall-PC/index/menu/hot // https://www.imooc.com/api/mall-PC/index/menu/hk
面向过程的写法,比较乱
function wait(ms) {
return new Promise(resolve => {
setTimeout(resolve, ms);
});
}
function getJSON(url) {
return new Promise(resolve => {
const xhr = new XMLHttpRequest();
xhr.addEventListener(
'load',
async () => {
if (
(xhr.status >= 200 && xhr.status < 300) ||
xhr.status === 304
) {
// 模拟网络延迟
await wait(1000);
resolve(xhr.response);
}
},
false
);
xhr.open('GET', url, true);
xhr.responseType = 'json';
xhr.send(null);
});
}
(async () => {
const url = 'https://www.imooc.com/api/mall-PC/index/menu';
const $menu = document.getElementById('menu');
// 发送请求,获取数据,创建主菜单
const menuResult = await getJSON(url);
// console.log(menuResult);
createMenu($menu, menuResult.data);
// 循环绑定事件,发送请求,获取数据,创建子菜单
const $items = $menu.getElementsByClassName('menu-item');
[...$items].forEach($item => {
$item.addEventListener(
'mouseenter',
async () => {
if ($item.dataset.done === 'done') return;
const subMenuResult = await getJSON(
`${url}/${$item.dataset.key}`
);
console.log(subMenuResult);
$item.dataset.done = 'done';
createSubMenu($item, subMenuResult.data);
},
false
);
});
})();
function createMenu($el, data) {
let html = '';
for (const item of data) {
html += `<li class="menu-item" data-key="${item.key}">
<span>${item.title}</span>
<div class="menu-content">
<img class="menu-loading" src="./loading.gif" alt="加载中" />
</div>
</li>`;
}
$el.innerHTML = html;
}
function createSubMenu($el, data) {
let html = '';
for (const item of data) {
html += `<p>${item.title}</p>`;
}
$el.querySelector('.menu-content').innerHTML = html;
}面向对象
前面的wait和getJSON都需要留下来
class Menu {
constructor($el) {
this.$el = $el;
this.url = 'https://www.imooc.com/api/mall-PC/index/menu';
}
async getData(url = this.url) {
return (await getJSON(url)).data;
}
render(data) {
let html = '';
for (const item of data) {
html += `<li class="menu-item" data-key="${item.key}">
<span>${item.title}</span>
<div class="menu-content">
<img class="menu-loading" src="./loading.gif" alt="加载中" />
</div>
</li>`;
}
this.$el.innerHTML = html;
}
}
class SubMenu {
constructor($el) {
this.$el = $el;
this.url = 'https://www.imooc.com/api/mall-PC/index/menu';
}
// 是否需要获取数据
needGetData() {
if (this.$el.dataset.done !== 'done') {
this.$el.dataset.done = 'done';
return true;
}
return false;
}
async getData(url = `${this.url}/${this.$el.dataset.key}`) {
return (await getJSON(url)).data;
}
render(data) {
let html = '';
for (const item of data) {
html += `<p>${item.title}</p>`;
}
this.$el.querySelector('.menu-content').innerHTML = html;
}
}
// 面向对象
(async () => {
const $menu = document.getElementById('menu');
// 发送请求,获取数据,创建主菜单
const menu = new Menu($menu);
menu.render(await menu.getData());
// 循环绑定事件,发送请求,获取数据,创建子菜单
const $items = $menu.getElementsByClassName('menu-item');
for (const $item of $items) {
$item.addEventListener(
'mouseenter',
async () => {
const subMenu = new SubMenu($item);
if (!subMenu.needGetData()) return;
subMenu.render(await subMenu.getData());
},
false
);
}
})();这里dataset.done 涉及到dataset的用法,详见:https://class.imooc.com/lesson/2123#mid=50481
课程收获:
这一节是实战课,老师讲的有点不太明白,但是太困了,明天再复习复习,期待明天的学习 。
随时随地看视频