接口文档
地区查询
- 图解
- 代码
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>案例_地区查询</title>
<link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/bootstrap@5.1.3/dist/css/bootstrap.min.css">
<style>
:root {
font-size: 15px;
}
body {
padding-top: 15px;
}
</style>
</head>
<body>
<div class="container">
<form id="editForm" class="row">
<!-- 输入省份名字 -->
<div class="mb-3 col">
<label class="form-label">省份名字</label>
<input type="text" value="北京" name="province" class="form-control province" placeholder="请输入省份名称" />
</div>
<!-- 输入城市名字 -->
<div class="mb-3 col">
<label class="form-label">城市名字</label>
<input type="text" value="北京市" name="city" class="form-control city" placeholder="请输入城市名称" />
</div>
</form>
<button type="button" class="btn btn-primary sel-btn">查询</button>
<br><br>
<p>地区列表: </p>
<ul class="list-group">
<!-- 示例地区 -->
<li class="list-group-item">东城区</li>
</ul>
</div>
<script src="https://cdn.jsdelivr.net/npm/axios/dist/axios.min.js"></script>
<script>
/*
获取地区列表: http://hmajax.itheima.net/api/area
查询参数:
pname: 省份或直辖市名字
cname: 城市名字
*/
// 目标: 根据省份和城市名字, 查询地区列表
// 1. 查询按钮-点击事件
document.querySelector('.sel-btn').addEventListener('click', () => {
// 2. 获取省份和城市名字
let pname = document.querySelector('.province').value
let cname = document.querySelector('.city').value
// 3. 基于axios请求地区列表数据
axios({
url: 'http://hmajax.itheima.net/api/area',
params: {
pname,
cname
}
}).then(result => {
// console.log(result)
// 4. 把数据转li标签插入到页面上
let list = result.data.list
console.log(list)
let theLi = list.map(areaName => `<li class="list-group-item">${areaName}</li>`).join('')
console.log(theLi)
document.querySelector('.list-group').innerHTML = theLi
})
})
</script>
</body>
</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>案例_登录_插件使用</title>
<!-- 引入bootstrap.css -->
<link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/bootstrap@5.2.2/dist/css/bootstrap.min.css">
<!-- 公共 -->
<style>
html,
body {
background-color: #EDF0F5;
width: 100%;
height: 100%;
display: flex;
justify-content: center;
align-items: center;
}
.container {
width: 520px;
height: 540px;
background-color: #fff;
padding: 60px;
box-sizing: border-box;
}
.container h3 {
font-weight: 900;
}
</style>
<!-- 表单容器和内容 -->
<style>
.form_wrap {
color: #8B929D !important;
}
.form-text {
color: #8B929D !important;
}
</style>
<!-- 提示框样式 -->
<style>
.alert {
transition: .5s;
opacity: 0;
}
.alert.show {
opacity: 1;
}
</style>
</head>
<body>
<div class="container">
<h3>欢迎-登录</h3>
<!-- 登录结果-提示框 -->
<div class="alert alert-success" role="alert">
提示消息
</div>
<!-- 表单 -->
<div class="form_wrap">
<form class="login-form">
<div class="mb-3">
<label for="username" class="form-label">账号名</label>
<input type="text" class="form-control username" name="username">
</div>
<div class="mb-3">
<label for="password" class="form-label">密码</label>
<input type="password" class="form-control password" name="password">
</div>
<button type="button" class="btn btn-primary btn-login"> 登 录 </button>
</form>
</div>
</div>
<script src="https://cdn.jsdelivr.net/npm/axios/dist/axios.min.js"></script>
<!-- 3.1 引入插件 -->
<script src="./lib/form-serialize.js"></script>
<script>
// 目标1:点击登录时,用户名和密码长度判断,并提交数据和服务器通信
// 目标2:使用提示框,反馈提示消息
// 目标3:使用form-serialize插件,收集用户名和密码
// 2.1 获取提示框
const myAlert = document.querySelector('.alert')
/**2.2 封装提示框函数,重复调用,满足提示需求
* 功能:
* 1. 显示提示框
* 2. 不同提示文字msg,和成功绿色失败红色isSuccess(true成功,false失败)
* 3. 过2秒后,让提示框自动消失
*/
function alertFn(msg, isSuccess) {
// 1> 显示提示框
myAlert.classList.add('show')
// 2> 实现细节
myAlert.innerText = msg
const bgStyle = isSuccess ? 'alert-success' : 'alert-danger'
myAlert.classList.add(bgStyle)
// 3> 过2秒隐藏
setTimeout(() => {
myAlert.classList.remove('show')
// 提示:避免类名冲突,重置背景色
myAlert.classList.remove(bgStyle)
}, 2000)
}
// 1.1 登录-点击事件
document.querySelector('.btn-login').addEventListener('click', () => {
// 3.2 使用serialize函数,收集登录表单里用户名和密码
const form = document.querySelector('.login-form')
const data = serialize(form, { hash: true, empty: true })
console.log(data)
// {username: 'itheima007', password: '7654321'}
const { username, password } = data
// 1.2 获取用户名和密码
// const username = document.querySelector('.username').value
// const password = document.querySelector('.password').value
console.log(username, password)
// 1.3 判断长度
if (username.length < 8) {
alertFn('用户名必须大于等于8位', false)
console.log('用户名必须大于等于8位')
return // 阻止代码继续执行
}
if (password.length < 6) {
alertFn('密码必须大于等于6位', false)
console.log('密码必须大于等于6位')
return // 阻止代码继续执行
}
// 1.4 基于axios提交用户名和密码
// console.log('提交数据到服务器')
axios({
url: 'http://hmajax.itheima.net/api/login',
method: 'POST',
data: {
username,
password
}
}).then(result => {
alertFn(result.data.message, true)
console.log(result)
console.log(result.data.message)
}).catch(error => {
alertFn(error.response.data.message, false)
console.log(error)
console.log(error.response.data.message)
})
})
</script>
</body>
</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>案例-图书管理</title>
<!-- 字体图标 -->
<link rel="stylesheet" href="https://at.alicdn.com/t/c/font_3736758_vxpb728fcyh.css">
<!-- 引入bootstrap.css -->
<link href="https://cdn.bootcdn.net/ajax/libs/twitter-bootstrap/5.2.3/css/bootstrap.min.css" rel="stylesheet">
<!-- 核心样式 -->
<link rel="stylesheet" href="./css/index.css">
</head>
<body>
<!-- 主体区域 -->
<div class="container">
<!-- 头部标题和添加按钮 -->
<div class="top">
<h3>图书管理</h3>
<button type="button" class="btn btn-primary plus-btn" data-bs-toggle="modal" data-bs-target=".add-modal"> + 添加
</button>
</div>
<!-- 数据列表 -->
<table class="table">
<thead class="table-light">
<tr>
<th style="width: 150px;">序号</th>
<th>书名</th>
<th>作者</th>
<th>出版社</th>
<th style="width: 180px;">操作</th>
</tr>
</thead>
<tbody class="list">
<tr>
<td>1</td>
<td>JavaScript程序设计</td>
<td>马特·弗里斯比</td>
<td>人民邮电出版社</td>
<td>
<span class="del">删除</span>
<span class="edit">编辑</span>
</td>
</tr>
</tbody>
</table>
</div>
<!-- 新增-弹出框 -->
<div class="modal fade add-modal">
<!-- 中间白色区域 -->
<div class="modal-dialog">
<div class="modal-content">
<div class="modal-header top">
<span>添加图书</span>
<button type="button" class="btn-close" aria-label="Close" data-bs-dismiss="modal"></button>
</div>
<div class="modal-body form-wrap">
<!-- 新增表单 -->
<form class="add-form">
<div class="mb-3">
<label for="bookname" class="form-label">书名</label>
<input type="text" class="form-control bookname" placeholder="请输入书籍名称" name="bookname">
</div>
<div class="mb-3">
<label for="author" class="form-label">作者</label>
<input type="text" class="form-control author" placeholder="请输入作者名称" name="author">
</div>
<div class="mb-3">
<label for="publisher" class="form-label">出版社</label>
<input type="text" class="form-control publisher" placeholder="请输入出版社名称" name="publisher">
</div>
</form>
</div>
<div class="modal-footer btn-group">
<button type="button" class="btn btn-primary" data-bs-dismiss="modal"> 取消 </button>
<button type="button" class="btn btn-primary add-btn"> 保存 </button>
</div>
</div>
</div>
</div>
<!-- 编辑-弹出框 -->
<div class="modal fade edit-modal">
<!-- 中间白色区域 -->
<div class="modal-dialog">
<div class="modal-content">
<div class="modal-header top">
<span>编辑图书</span>
<button type="button" class="btn-close" aria-label="Close" data-bs-dismiss="modal"></button>
</div>
<div class="modal-body form-wrap">
<!-- 编辑表单 -->
<form class="edit-form">
<input type="hidden" class="id" name="id">
<div class="mb-3">
<label for="bookname" class="form-label">书名</label>
<input type="text" class="form-control bookname" placeholder="请输入书籍名称" name="bookname">
</div>
<div class="mb-3">
<label for="author" class="form-label">作者</label>
<input type="text" class="form-control author" placeholder="请输入作者名称" name="author">
</div>
<div class="mb-3">
<label for="publisher" class="form-label">出版社</label>
<input type="text" class="form-control publisher" placeholder="请输入出版社名称" name="publisher">
</div>
</form>
</div>
<div class="modal-footer btn-group">
<button type="button" class="btn btn-primary" data-bs-dismiss="modal"> 取消 </button>
<button type="button" class="btn btn-primary edit-btn"> 修改 </button>
</div>
</div>
</div>
</div>
<script src="https://cdn.bootcdn.net/ajax/libs/axios/1.2.0/axios.min.js"></script>
<script src="./lib/form-serialize.js"></script>
<script src="https://cdn.bootcdn.net/ajax/libs/twitter-bootstrap/5.2.3/js/bootstrap.min.js"></script>
<!-- 核心逻辑 -->
<script src="./js/index.js"></script>
</body>
</html>
javascript
/**
* 目标1:渲染图书列表
* 1.1 获取数据
* 1.2 渲染数据
*/
const creator = '老张'
// 封装-获取并渲染图书列表函数
function getBooksList() {
// 1.1 获取数据
axios({
url: 'http://hmajax.itheima.net/api/books',
params: {
// 外号:获取对应数据
creator
}
}).then(result => {
// console.log(result)
const bookList = result.data.data
// console.log(bookList)
// 1.2 渲染数据
const htmlStr = bookList.map((item, index) => {
return `<tr>
<td>${index + 1}</td>
<td>${item.bookname}</td>
<td>${item.author}</td>
<td>${item.publisher}</td>
<td data-id=${item.id}>
<span class="del">删除</span>
<span class="edit">编辑</span>
</td>
</tr>`
}).join('')
// console.log(htmlStr)
document.querySelector('.list').innerHTML = htmlStr
})
}
// 网页加载运行,获取并渲染列表一次
getBooksList()
/**
* 目标2:新增图书
* 2.1 新增弹框->显示和隐藏
* 2.2 收集表单数据,并提交到服务器保存
* 2.3 刷新图书列表
*/
// 2.1 创建弹框对象
const addModalDom = document.querySelector('.add-modal')
const addModal = new bootstrap.Modal(addModalDom)
// 保存按钮->点击->隐藏弹框
document.querySelector('.add-btn').addEventListener('click', () => {
// 2.2 收集表单数据,并提交到服务器保存
const addForm = document.querySelector('.add-form')
const bookObj = serialize(addForm, { hash: true, empty: true })
// console.log(bookObj)
// 提交到服务器
axios({
url: 'http://hmajax.itheima.net/api/books',
method: 'POST',
data: {
...bookObj,
creator
}
}).then(result => {
// console.log(result)
// 2.3 添加成功后,重新请求并渲染图书列表
getBooksList()
// 重置表单
addForm.reset()
// 隐藏弹框
addModal.hide()
})
})
/**
* 目标3:删除图书
* 3.1 删除元素绑定点击事件->获取图书id
* 3.2 调用删除接口
* 3.3 刷新图书列表
*/
// 3.1 删除元素->点击(事件委托)
document.querySelector('.list').addEventListener('click', e => {
// 获取触发事件目标元素
// console.log(e.target)
// 判断点击的是删除元素
if (e.target.classList.contains('del')) {
// console.log('点击删除元素')
// 获取图书id(自定义属性id)
const theId = e.target.parentNode.dataset.id
// console.log(theId)
// 3.2 调用删除接口
axios({
url: `http://hmajax.itheima.net/api/books/${theId}`,
method: 'DELETE'
}).then(() => {
// 3.3 刷新图书列表
getBooksList()
})
}
})
/**
* 目标4:编辑图书
* 4.1 编辑弹框->显示和隐藏
* 4.2 获取当前编辑图书数据->回显到编辑表单中
* 4.3 提交保存修改,并刷新列表
*/
// 4.1 编辑弹框->显示和隐藏
const editDom = document.querySelector('.edit-modal')
const editModal = new bootstrap.Modal(editDom)
// 编辑元素->点击->弹框显示
document.querySelector('.list').addEventListener('click', e => {
// 判断点击的是否为编辑元素
if (e.target.classList.contains('edit')) {
// 4.2 获取当前编辑图书数据->回显到编辑表单中
const theId = e.target.parentNode.dataset.id
axios({
url: `http://hmajax.itheima.net/api/books/${theId}`
}).then(result => {
const bookObj = result.data.data
// document.querySelector('.edit-form .bookname').value = bookObj.bookname
// document.querySelector('.edit-form .author').value = bookObj.author
// 数据对象"属性"和标签"类名"一致
// 遍历数据对象,使用属性去获取对应的标签,快速赋值
const keys = Object.keys(bookObj) // ['id', 'bookname', 'author', 'publisher']
keys.forEach(key => {
document.querySelector(`.edit-form .${key}`).value = bookObj[key]
})
})
editModal.show()
}
})
// 修改按钮->点击->隐藏弹框
document.querySelector('.edit-btn').addEventListener('click', () => {
// 4.3 提交保存修改,并刷新列表
const editForm = document.querySelector('.edit-form')
const { id, bookname, author, publisher } = serialize(editForm, { hash: true, empty: true})
// 保存正在编辑的图书id,隐藏起来:无需让用户修改
// <input type="hidden" class="id" name="id" value="84783">
axios({
url: `http://hmajax.itheima.net/api/books/${id}`,
method: 'PUT',
data: {
bookname,
author,
publisher,
creator
}
}).then(() => {
// 修改成功以后,重新获取并刷新列表
getBooksList()
// 隐藏弹框
editModal.hide()
})
})
图片上传
- 图解
- 代码
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>图片上传</title>
</head>
<body>
<!-- 文件选择元素 -->
<input type="file" class="upload">
<img src="" alt="" class="my-img">
<script src="https://cdn.jsdelivr.net/npm/axios/dist/axios.min.js"></script>
<script>
/**
* 目标:图片上传,显示到网页上
* 1. 获取图片文件
* 2. 使用 FormData 携带图片文件
* 3. 提交到服务器,获取图片url网址使用
*/
// 文件选择元素->change改变事件
document.querySelector('.upload').addEventListener('change', e => {
// 1. 获取图片文件
console.log(e.target.files[0])
// 2. 使用 FormData 携带图片文件
const fd = new FormData()
fd.append('img', e.target.files[0])
// 3. 提交到服务器,获取图片url网址使用
axios({
url: 'http://hmajax.itheima.net/api/uploadimg',
method: 'POST',
data: fd
}).then(result => {
console.log(result)
// 取出图片url网址,用img标签加载显示
const imgUrl = result.data.data.url
document.querySelector('.my-img').src = imgUrl
})
})
</script>
</body>
</html>
更换网站背景图
- 图解
- 代码
html
<!DOCTYPE html>
<html lang="zh-CN">
<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>网站-更换背景</title>
<!-- 初始化样式 -->
<link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/reset.css@2.0.2/reset.min.css">
<!-- 核心样式 -->
<link rel="stylesheet" href="./css/index.css">
</head>
<body>
<div class="container">
<div class="nav">
<div class="left">
<ul>
<li><a href="http://yun.itheima.com/?webzly" target="_blank" rel="nofollow">免费教程</a></li>
<li><a href="http://resource.ityxb.com/booklist/?webzly" target="_blank" rel="nofollow">原创书籍</a></li>
<li><a href="http://www.itheima.com/teacher.html?webzly#ajavaee" target="_blank" rel="nofollow">教研团队</a></li>
<li><a href="http://www.itheima.com/special/hmschool/index.shtml?webzly" target="_blank" rel="nofollow">校区汇总</a></li>
<li><a href="http://www.itheima.com/flow/flow.html?webzly" target="_blank" rel="nofollow">报名流程</a></li>
<li><a href="https://pip.itcast.cn?hmgw$webzly" target="_blank" rel="nofollow">项目信息站</a></li>
<li><a href="http://bbs.itheima.com/forum.php?webzly" target="_blank" rel="nofollow">技术社区</a></li>
</ul>
</div>
<div class="right">
<label for="bg">更换背景</label>
<input class="bg-ipt" type="file" id="bg">
</div>
</div>
<div class="search-container">
<img src="https://www.itheima.com/images/logo.png" alt="">
<div class="search-box">
<input type="text">
<button>搜索一下</button>
</div>
</div>
</div>
<script src="https://cdn.jsdelivr.net/npm/axios/dist/axios.min.js"></script>
<!-- 核心代码 -->
<script src="./js/index.js"></script>
</body>
</html>
javascript
/**
* 目标:网站-更换背景
* 1. 选择图片上传,设置body背景
* 2. 上传成功时,"保存"图片url网址
* 3. 网页运行后,"获取"url网址使用
* */
document.querySelector('.bg-ipt').addEventListener('change', e => {
// 1. 选择图片上传,设置body背景
console.log(e.target.files[0])
const fd = new FormData()
fd.append('img', e.target.files[0])
axios({
url: 'http://hmajax.itheima.net/api/uploadimg',
method: 'POST',
data: fd
}).then(result => {
const imgUrl = result.data.data.url
document.body.style.backgroundImage = `url(${imgUrl})`
// 2. 上传成功时,"保存"图片url网址
localStorage.setItem('bgImg', imgUrl)
})
})
// 3. 网页运行后,"获取"url网址使用
const bgUrl = localStorage.getItem('bgImg')
console.log(bgUrl)
bgUrl && (document.body.style.backgroundImage = `url(${bgUrl})`)
个人信息设置
- 图解
- 代码
html
<!DOCTYPE html>
<html lang="zh-CN">
<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">
<link href="https://cdn.jsdelivr.net/npm/bootstrap@5.2.3/dist/css/bootstrap.min.css" rel="stylesheet">
<!-- 核心样式 -->
<link rel="stylesheet" href="./css/index.css">
<title>个人信息设置</title>
</head>
<body>
<!-- toast 提示框 -->
<div class="toast my-toast" data-bs-delay="1500">
<div class="toast-body">
<div class="alert alert-success info-box">
操作成功
</div>
</div>
</div>
<!-- 核心内容区域 -->
<div class="container">
<ul class="my-nav">
<li class="active">基本设置</li>
<li>安全设置</li>
<li>账号绑定</li>
<li>新消息通知</li>
</ul>
<div class="content">
<div class="info-wrap">
<h3 class="title">基本设置</h3>
<form class="user-form" action="javascript:;">
<div class="form-item">
<label for="email">邮箱</label>
<input id="email" name="email" class="email" type="text" placeholder="请输入邮箱" autocomplete="off">
</div>
<div class="form-item">
<label for="nickname">昵称</label>
<input id="nickname" name="nickname" class="nickname" type="text" placeholder="请输入昵称" autocomplete="off">
</div>
<div class="form-item">
<label>性别</label>
<label class="male-label"><input type="radio" name="gender" class="gender" value="0">男</label>
<label class="male-label"><input type="radio" name="gender" class="gender" value="1">女</label>
</div>
<div class="form-item">
<label for="desc">个人简介</label>
<textarea id="desc" name="desc" class="desc" placeholder="请输入个人简介" cols="20" rows="10" autocomplete="off"></textarea>
</div>
<button class="submit">提交</button>
</form>
</div>
<div class="avatar-box">
<h4 class="avatar-title">头像</h3>
<img class="prew" src="./img/头像.png" alt="">
<label for="upload">更换头像</label>
<input id="upload" type="file" class="upload">
</div>
</div>
</div>
<script src="https://cdn.jsdelivr.net/npm/axios/dist/axios.min.js"></script>
<script src="https://cdn.jsdelivr.net/npm/bootstrap@5.2.3/dist/js/bootstrap.min.js"></script>
<script src="./lib/form-serialize.js"></script>
<!-- 核心逻辑 -->
<script src="./js/index.js"></script>
</body>
</html>
javascript
/**
* 目标1:信息渲染
* 1.1 获取用户的数据
* 1.2 回显数据到标签上
* */
const creator = '播仔'
// 1.1 获取用户的数据
axios({
url: 'http://hmajax.itheima.net/api/settings',
params: {
creator
}
}).then(result => {
const userObj = result.data.data
// 1.2 回显数据到标签上
Object.keys(userObj).forEach(key => {
if (key === 'avatar') {
// 赋予默认头像
document.querySelector('.prew').src = userObj[key]
} else if (key === 'gender') {
// 赋予默认性别
// 获取性别单选框:[男radio元素,女radio元素]
const gRadioList = document.querySelectorAll('.gender')
// 获取性别数字:0男,1女
const gNum = userObj[key]
// 通过性别数字,作为下标,找到对应性别单选框,设置选中状态
gRadioList[gNum].checked = true
} else {
// 赋予默认内容
document.querySelector(`.${key}`).value = userObj[key]
}
})
})
/**
* 目标2:修改头像
* 2.1 获取头像文件
* 2.2 提交服务器并更新头像
* */
// 文件选择元素->change事件
document.querySelector('.upload').addEventListener('change', e => {
// 2.1 获取头像文件
console.log(e.target.files[0])
const fd = new FormData()
fd.append('avatar', e.target.files[0])
fd.append('creator', creator)
// 2.2 提交服务器并更新头像
axios({
url: 'http://hmajax.itheima.net/api/avatar',
method: 'PUT',
data: fd
}).then(result => {
const imgUrl = result.data.data.avatar
// 把新的头像回显到页面上
document.querySelector('.prew').src = imgUrl
})
})
/**
* 目标3:提交表单
* 3.1 收集表单信息
* 3.2 提交到服务器保存
*/
/**
* 目标4:结果提示
* 4.1 创建toast对象
* 4.2 调用show方法->显示提示框
*/
// 保存修改->点击
document.querySelector('.submit').addEventListener('click', () => {
// 3.1 收集表单信息
const userForm = document.querySelector('.user-form')
const userObj = serialize(userForm, { hash: true, empty: true })
userObj.creator = creator
// 性别数字字符串,转成数字类型
userObj.gender = +userObj.gender
console.log(userObj)
// 3.2 提交到服务器保存
axios({
url: 'http://hmajax.itheima.net/api/settings',
method: 'PUT',
data: userObj
}).then(result => {
// 4.1 创建toast对象
const toastDom = document.querySelector('.my-toast')
const toast = new bootstrap.Toast(toastDom)
// 4.2 调用show方法->显示提示框
toast.show()
})
})
原生XHR地区查询
- 图解
- 代码
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>案例_地区查询</title>
<link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/bootstrap@5.1.3/dist/css/bootstrap.min.css">
<style>
:root {
font-size: 15px;
}
body {
padding-top: 15px;
}
</style>
</head>
<body>
<div class="container">
<form id="editForm" class="row">
<!-- 输入省份名字 -->
<div class="mb-3 col">
<label class="form-label">省份名字</label>
<input type="text" value="北京" name="province" class="form-control province" placeholder="请输入省份名称" />
</div>
<!-- 输入城市名字 -->
<div class="mb-3 col">
<label class="form-label">城市名字</label>
<input type="text" value="北京市" name="city" class="form-control city" placeholder="请输入城市名称" />
</div>
</form>
<button type="button" class="btn btn-primary sel-btn">查询</button>
<br><br>
<p>地区列表: </p>
<ul class="list-group">
<!-- 示例地区 -->
<li class="list-group-item">东城区</li>
</ul>
</div>
<script src="https://cdn.jsdelivr.net/npm/axios/dist/axios.min.js"></script>
<script>
/**
* 目标: 根据省份和城市名字, 查询对应的地区列表
*/
// 1. 查询按钮-点击事件
document.querySelector('.sel-btn').addEventListener('click', () => {
// 2. 收集省份和城市名字
const pname = document.querySelector('.province').value
const cname = document.querySelector('.city').value
// 3. 组织查询参数字符串
const qObj = {
pname,
cname
}
// 查询参数对象 -> 查询参数字符串
const paramsObj = new URLSearchParams(qObj)
const queryString = paramsObj.toString()
console.log(queryString)
// 4. 使用XHR对象,查询地区列表
const xhr = new XMLHttpRequest()
xhr.open('GET', `http://hmajax.itheima.net/api/area?${queryString}`)
xhr.addEventListener('loadend', () => {
console.log(xhr.response)
const data = JSON.parse(xhr.response)
console.log(data)
const htmlStr = data.list.map(areaName => {
return `<li class="list-group-item">${areaName}</li>`
}).join('')
console.log(htmlStr)
document.querySelector('.list-group').innerHTML = htmlStr
})
xhr.send()
})
</script>
</body>
</html>
天气预报
- 图解
- 代码
index.html
html
<!DOCTYPE html>
<html lang="zh-CN">
<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">
<link rel="stylesheet" href="./css/reset.css">
<link rel="stylesheet" href="./css/index.css">
<title>案例_天气预报</title>
</head>
<body>
<div class="container">
<!-- 顶部 -->
<div class="top-box">
<div class="title">
<span class="dateShort">10月28日</span>
<span class="calendar">农历
<span class="dateLunar">十月初四</span>
</span>
</div>
<div class="search-box">
<div class="location">
<img src="./imgs/定位.png" alt="">
<span class="area">城市名</span>
</div>
<!-- 搜索框+搜索列表 -->
<div class="search">
<input type="text" class="search-city" placeholder="搜索城市">
<ul class="search-list">
<li class="city-item">北京市</li>
</ul>
</div>
</div>
</div>
<!-- 当前天气 -->
<div class="weather-box">
<div class="tem-box">
<span class="temp">
<span class="temperature">12</span>
<span>°</span>
</span>
</div>
<div class="climate-box">
<div class="air">
<span class="psPm25">55</span>
<span class="psPm25Level">良</span>
</div>
<ul class="weather-list">
<li>
<img src="./imgs/小雨-line.png" class="weatherImg" alt="">
<span class="weather">多云</span>
</li>
<li class="windDirection">东南风</li>
<li class="windPower">2级</li>
</ul>
</div>
</div>
<div class="today-weather">
<div class="range-box">
<span>今天:</span>
<span class="range">
<span class="weather">晴</span>
<span class="temNight">9</span>
<span>-</span>
<span class="temDay">14</span>
<span>℃</span>
</span>
</div>
<ul class="sun-list">
<li>
<span>紫外线</span>
<span class="ultraviolet">强</span>
</li>
<li>
<span>湿度</span>
<span class="humidity">53</span>%
</li>
<li>
<span>日出</span>
<span class="sunriseTime">06:38</span>
</li>
<li>
<span>日落</span>
<span class="sunsetTime">17:18</span>
</li>
</ul>
</div>
<!-- 周天气预报 -->
<div class="week-weather-box">
<div class="title">7日内天气预报</div>
<ul class="week-wrap">
<li class="item">
<div class="date-box">
<span class="dateFormat">今天</span>
<span class="date">10月28日</span>
</div>
<img src="./imgs/多云.png" alt="" class="weatherImg">
<span class="weather">多云</span>
<div class="temp">
<span class="temNight">12</span>-
<span class="temDay">12</span>
<span>℃</span>
</div>
<div class="wind">
<span class="windDirection">东南风</span>
<span class="windPower"><3级</span>
</div>
</li>
<li class="item">
<div class="date-box">
<span class="dateFormat">今天</span>
<span class="date">10月28日</span>
</div>
<img src="./imgs/多云.png" alt="" class="weatherImg">
<span class="weather">多云</span>
<div class="temp">
<span class="temDay">12</span>-
<span class="temNight">12</span>
<span>℃</span>
</div>
<div class="wind">
<span class="windDirection">东南风</span>
<span class="windPower"><3级</span>
</div>
</li>
<li class="item">
<div class="date-box">
<span class="dateFormat">今天</span>
<span class="date">10月28日</span>
</div>
<img src="./imgs/多云.png" alt="" class="weatherImg">
<span class="weather">多云</span>
<div class="temp">
<span class="temDay">12</span>-
<span class="temNight">12</span>
<span>℃</span>
</div>
<div class="wind">
<span class="windDirection">东南风</span>
<span class="windPower"><3级</span>
</div>
</li>
<li class="item">
<div class="date-box">
<span class="dateFormat">今天</span>
<span class="date">10月28日</span>
</div>
<img src="./imgs/多云.png" alt="" class="weatherImg">
<span class="weather">多云</span>
<div class="temp">
<span class="temDay">12</span>-
<span class="temNight">12</span>
<span>℃</span>
</div>
<div class="wind">
<span class="windDirection">东南风</span>
<span class="windPower"><3级</span>
</div>
</li>
<li class="item">
<div class="date-box">
<span class="dateFormat">今天</span>
<span class="date">10月28日</span>
</div>
<img src="./imgs/多云.png" alt="" class="weatherImg">
<span class="weather">多云</span>
<div class="temp">
<span class="temDay">12</span>-
<span class="temNight">12</span>
<span>℃</span>
</div>
<div class="wind">
<span class="windDirection">东南风</span>
<span class="windPower"><3级</span>
</div>
</li>
<li class="item">
<div class="date-box">
<span class="dateFormat">今天</span>
<span class="date">10月28日</span>
</div>
<img src="./imgs/多云.png" alt="" class="weatherImg">
<span class="weather">多云</span>
<div class="temp">
<span class="temDay">12</span>-
<span class="temNight">12</span>
<span>℃</span>
</div>
<div class="wind">
<span class="windDirection">东南风</span>
<span class="windPower"><3级</span>
</div>
</li>
<li class="item">
<div class="date-box">
<span class="dateFormat">今天</span>
<span class="date">10月28日</span>
</div>
<img src="./imgs/多云.png" alt="" class="weatherImg">
<span class="weather">多云</span>
<div class="temp">
<span class="temDay">12</span>-
<span class="temNight">12</span>
<span>℃</span>
</div>
<div class="wind">
<span class="windDirection">东南风</span>
<span class="windPower"><3级</span>
</div>
</li>
</ul>
</div>
</div>
<!-- 自己封装myAxios函数 -->
<script src="./js/my-axios.js"></script>
<!-- 搜索框+下拉菜单出现逻辑 -->
<script src="./js/search.js"></script>
<!-- 核心js -->
<script src="./js/index.js"></script>
</body>
</html>
index.js
javascript
/**
* 目标1:默认显示-北京市天气
* 1.1 获取北京市天气数据
* 1.2 数据展示到页面
*/
// 获取并渲染城市天气函数
function getWeather(cityCode) {
// 1.1 获取北京市天气数据
myAxios({
url: 'http://hmajax.itheima.net/api/weather',
params: {
city: cityCode
}
}).then(result => {
console.log(result)
const wObj = result.data
// 1.2 数据展示到页面
// 阳历和农历日期
const dateStr = `<span class="dateShort">${wObj.date}</span>
<span class="calendar">农历
<span class="dateLunar">${wObj.dateLunar}</span>
</span>`
document.querySelector('.title').innerHTML = dateStr
// 城市名字
document.querySelector('.area').innerHTML = wObj.area
// 当天气温
const nowWStr = `<div class="tem-box">
<span class="temp">
<span class="temperature">${wObj.temperature}</span>
<span>°</span>
</span>
</div>
<div class="climate-box">
<div class="air">
<span class="psPm25">${wObj.psPm25}</span>
<span class="psPm25Level">${wObj.psPm25Level}</span>
</div>
<ul class="weather-list">
<li>
<img src="${wObj.weatherImg}" class="weatherImg" alt="">
<span class="weather">${wObj.weather}</span>
</li>
<li class="windDirection">${wObj.windDirection}</li>
<li class="windPower">${wObj.windPower}</li>
</ul>
</div>`
document.querySelector('.weather-box').innerHTML = nowWStr
// 当天天气
const twObj = wObj.todayWeather
const todayWStr = `<div class="range-box">
<span>今天:</span>
<span class="range">
<span class="weather">${twObj.weather}</span>
<span class="temNight">${twObj.temNight}</span>
<span>-</span>
<span class="temDay">${twObj.temDay}</span>
<span>℃</span>
</span>
</div>
<ul class="sun-list">
<li>
<span>紫外线</span>
<span class="ultraviolet">${twObj.ultraviolet}</span>
</li>
<li>
<span>湿度</span>
<span class="humidity">${twObj.humidity}</span>%
</li>
<li>
<span>日出</span>
<span class="sunriseTime">${twObj.sunriseTime}</span>
</li>
<li>
<span>日落</span>
<span class="sunsetTime">${twObj.sunsetTime}</span>
</li>
</ul>`
document.querySelector('.today-weather').innerHTML = todayWStr
// 7日天气预报数据展示
const dayForecast = wObj.dayForecast
const dayForecastStr = dayForecast.map(item => {
return `<li class="item">
<div class="date-box">
<span class="dateFormat">${item.dateFormat}</span>
<span class="date">${item.date}</span>
</div>
<img src="${item.weatherImg}" alt="" class="weatherImg">
<span class="weather">${item.weather}</span>
<div class="temp">
<span class="temNight">${item.temNight}</span>-
<span class="temDay">${item.temDay}</span>
<span>℃</span>
</div>
<div class="wind">
<span class="windDirection">${item.windDirection}</span>
<span class="windPower">${item.windPower}</span>
</div>
</li>`
}).join('')
// console.log(dayForecastStr)
document.querySelector('.week-wrap').innerHTML = dayForecastStr
})
}
// 默认进入网页-就要获取天气数据(北京市城市编码:'110100')
getWeather('110100')
/**
* 目标2:搜索城市列表
* 2.1 绑定input事件,获取关键字
* 2.2 获取展示城市列表数据
*/
// 2.1 绑定input事件,获取关键字
document.querySelector('.search-city').addEventListener('input', (e) => {
console.log(e.target.value)
// 2.2 获取展示城市列表数据
myAxios({
url: 'http://hmajax.itheima.net/api/weather/city',
params: {
city: e.target.value
}
}).then(result => {
console.log(result)
const liStr = result.data.map(item => {
return `<li class="city-item" data-code="${item.code}">${item.name}</li>`
}).join('')
console.log(liStr)
document.querySelector('.search-list').innerHTML = liStr
})
})
/**
* 目标3:切换城市天气
* 3.1 绑定城市点击事件,获取城市code值
* 3.2 调用获取并展示天气的函数
*/
// 3.1 绑定城市点击事件,获取城市code值
document.querySelector('.search-list').addEventListener('click', e => {
if (e.target.classList.contains('city-item')) {
// 只有点击城市li才会走这里
const cityCode = e.target.dataset.code
console.log(cityCode)
// 3.2 调用获取并展示天气的函数
getWeather(cityCode)
}
})
my-axios.js
javascript
function myAxios(config) {
return new Promise((resolve, reject) => {
const xhr = new XMLHttpRequest()
if (config.params) {
const paramsObj = new URLSearchParams(config.params)
const queryString = paramsObj.toString()
config.url += `?${queryString}`
}
xhr.open(config.method || 'GET', config.url)
xhr.addEventListener('loadend', () => {
if (xhr.status >= 200 && xhr.status < 300) {
resolve(JSON.parse(xhr.response))
} else {
reject(new Error(xhr.response))
}
})
if (config.data) {
const jsonStr = JSON.stringify(config.data)
xhr.setRequestHeader('Content-Type', 'application/json')
xhr.send(jsonStr)
} else {
xhr.send()
}
})
}
search.js
javascript
// 控制搜索列表,显示/隐藏
const searchList = document.querySelector('.search-list')
// 输入框内容改变时,有城市关键字出现列表,没有则不出现列表
document.querySelector('.search-city').addEventListener('input', e => {
if (e.target.value.length > 0) {
searchList.classList.add('show')
} else {
searchList.classList.remove('show')
}
})
// 输入框失焦,隐藏搜索列表
document.querySelector('.search-city').addEventListener('blur', e => {
// 延迟消失,保证点击获取到城市code后,再隐藏下拉列表
setTimeout(() => {
searchList.classList.remove('show')
}, 500)
})
// 输入框聚焦,显示搜索列表
document.querySelector('.search-city').addEventListener('focus', e => {
if (e.target.value.length > 0) {
searchList.classList.add('show')
}
})
商品分类
- 图解
- 代码
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>案例_分类导航</title>
<link rel="stylesheet" href="./css/index.css">
</head>
<body>
<!-- 大容器 -->
<div class="container">
<div class="sub-list">
<div class="item">
<h3>分类名字</h3>
<ul>
<li>
<a href="javascript:;">
<img src="http://zhoushugang.gitee.io/erabbit-client-pc-static/uploads/img/category%20(9).png" />
<p>巧克力</p>
</a>
</li>
<li>
<a href="javascript:;">
<img src="http://zhoushugang.gitee.io/erabbit-client-pc-static/uploads/img/category%20(9).png" />
<p>巧克力</p>
</a>
</li>
<li>
<a href="javascript:;">
<img src="http://zhoushugang.gitee.io/erabbit-client-pc-static/uploads/img/category%20(9).png" />
<p>巧克力</p>
</a>
</li>
</ul>
</div>
</div>
</div>
<script src="https://cdn.jsdelivr.net/npm/axios/dist/axios.min.js"></script>
<script>
/**
* 目标:把所有商品分类"同时"渲染到页面上
* 1. 获取所有一级分类数据
* 2. 遍历id,创建获取二级分类请求
* 3. 合并所有二级分类Promise对象
* 4. 等待同时成功后,渲染页面
*/
// 1. 获取所有一级分类数据
axios({
url: 'http://hmajax.itheima.net/api/category/top'
}).then(result => {
console.log(result)
// 2. 遍历id,创建获取二级分类请求
const secPromiseList = result.data.data.map(item => {
return axios({
url: 'http://hmajax.itheima.net/api/category/sub',
params: {
id: item.id // 一级分类id
}
})
})
console.log(secPromiseList) // [二级分类请求Promise对象,二级分类请求Promise对象,...]
// 3. 合并所有二级分类Promise对象
const p = Promise.all(secPromiseList)
p.then(result => {
console.log(result)
// 4. 等待同时成功后,渲染页面
const htmlStr = result.map(item => {
const dataObj = item.data.data // 取出关键数据对象
return `<div class="item">
<h3>${dataObj.name}</h3>
<ul>
${dataObj.children.map(item => {
return `<li>
<a href="javascript:;">
<img src="${item.picture}">
<p>${item.name}</p>
</a>
</li>`
}).join('')}
</ul>
</div>`
}).join('')
console.log(htmlStr)
document.querySelector('.sub-list').innerHTML = htmlStr
})
})
</script>
</body>
</html>
省市切换
- 图解
- 代码
html
<!DOCTYPE html>
<html lang="zh-CN">
<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">
<!-- 初始化样式 -->
<link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/reset.css@2.0.2/reset.min.css">
<!-- 引入bootstrap.css -->
<link href="https://cdn.bootcdn.net/ajax/libs/twitter-bootstrap/5.2.3/css/bootstrap.min.css" rel="stylesheet">
<!-- 核心样式 -->
<link rel="stylesheet" href="./css/index.css">
<title>学习反馈</title>
</head>
<body>
<div class="container">
<h4 class="stu-title">学习反馈</h4>
<img class="bg" src="./img/head.png" alt="">
<div class="item-wrap">
<div class="hot-area">
<span class="hot">热门校区</span>
<ul class="nav">
<li><a target="_blank" href="http://bjcp.itheima.com/">北京</a> </li>
<li><a target="_blank" href="http://sh.itheima.com/">上海</a> </li>
<li><a target="_blank" href="http://gz.itheima.com/">广州</a> </li>
<li><a target="_blank" href="http://sz.itheima.com/">深圳</a> </li>
</ul>
</div>
<form class="info-form">
<div class="area-box">
<span class="title">地区选择</span>
<select name="province" class="province">
<option value="">省份</option>
</select>
<select name="city" class="city">
<option value="">城市</option>
</select>
<select name="area" class="area">
<option value="">地区</option>
</select>
</div>
<div class="area-box">
<span class="title">您的称呼</span>
<input type="text" name="nickname" class="nickname" value="播仔">
</div>
<div class="area-box">
<span class="title">宝贵建议</span>
<textarea type="text" name="feedback" class="feedback" placeholder="您对AJAX阶段课程宝贵的建议"></textarea>
</div>
<div class="area-box">
<button type="button" class="btn btn-secondary submit">
确定提交
</button>
</div>
</form>
</div>
</div>
<script src="https://cdn.bootcdn.net/ajax/libs/axios/1.2.0/axios.min.js"></script>
<script src="./js/form-serialize.js"></script>
<!-- 核心代码 -->
<script src="./js/index.js"></script>
</body>
</html>
javascript
/**
* 目标1:完成省市区下拉列表切换
* 1.1 设置省份下拉菜单数据
* 1.2 切换省份,设置城市下拉菜单数据,清空地区下拉菜单
* 1.3 切换城市,设置地区下拉菜单数据
*/
// 1.1 设置省份下拉菜单数据
axios({
url: 'http://hmajax.itheima.net/api/province'
}).then(result => {
const optionStr = result.data.list.map(pname => `<option value="${pname}">${pname}</option>`).join('')
document.querySelector('.province').innerHTML = `<option value="">省份</option>` + optionStr
})
// 1.2 切换省份,设置城市下拉菜单数据,清空地区下拉菜单
document.querySelector('.province').addEventListener('change', async e => {
// 获取用户选择省份名字
// console.log(e.target.value)
const result = await axios({ url: 'http://hmajax.itheima.net/api/city', params: { pname: e.target.value } })
const optionStr = result.data.list.map(cname => `<option value="${cname}">${cname}</option>`).join('')
// 把默认城市选项+下属城市数据插入select中
document.querySelector('.city').innerHTML = `<option value="">城市</option>` + optionStr
// 清空地区数据
document.querySelector('.area').innerHTML = `<option value="">地区</option>`
})
// 1.3 切换城市,设置地区下拉菜单数据
document.querySelector('.city').addEventListener('change', async e => {
console.log(e.target.value)
const result = await axios({url: 'http://hmajax.itheima.net/api/area', params: {
pname: document.querySelector('.province').value,
cname: e.target.value
}})
console.log(result)
const optionStr = result.data.list.map(aname => `<option value="${aname}">${aname}</option>`).join('')
console.log(optionStr)
document.querySelector('.area').innerHTML = `<option value="">地区</option>` + optionStr
})
/**
* 目标2:收集数据提交保存
* 2.1 监听提交的点击事件
* 2.2 依靠插件收集表单数据
* 2.3 基于axios提交保存,显示结果
*/
// 2.1 监听提交的点击事件
document.querySelector('.submit').addEventListener('click', async () => {
// 2.2 依靠插件收集表单数据
const form = document.querySelector('.info-form')
const data = serialize(form, { hash: true, empty: true })
console.log(data)
// 2.3 基于axios提交保存,显示结果
try {
const result = await axios({
url: 'http://hmajax.itheima.net/api/feedback',
method: 'POST',
data
})
console.log(result)
alert(result.data.message)
} catch (error) {
console.dir(error)
alert(error.response.data.message)
}
})