案例一:更换网站背景
JS核心代码
<script>
document.querySelector('.bg-ipt').addEventListener('change', e => {
//选择图片上传,设置body背景
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})`
//上传成功保存图片网址
localStorage.setItem('bgImg', imgUrl)
})
})
//网页运行后直接获取图片url网址
const bgUrl = localStorage.getItem('bgImg')
//本地有背景图地址才设置
bgUrl && (document.body.style.backgroundImage = `url(${bgUrl})`)
</script>
案例叮嘱:
明确核心步骤:STEP1:选择图片上传,设置body背景
STEP2:上传成功时,保存url网址
STEP3:网页运行后,获取url网址使用
1.上传图片资源后对服务器返回的数据进行处理,将其设置为body背景,注意body部分的样式修改不需要先获取元素可以直接修改,顺带将图片网址保存在本地存储中
图片上传
1.获取图片文件对象
2.使用 FormData 携带图片文件
3.提交表单数据到服务器,使用图片 url 网址
2. 网页运行后直接获取图片url网址,但是需要注意只有当本地有背景图地址才设置
这里注意使用&&的逻辑中断
案例二:个人信息设置
模块一:信息渲染
//一打开网页就需要获取用户的数据
const creator = '在逃的吗喽'
axios({
url: 'http://hmajax.itheima.net/api/settings',
params: {
creator
}
}).then(result => {
const userObj = result.data.data
//回显数据到标签上
Object.keys(userObj).forEach(key => {
//需要对头像和性别进行特殊处理
if (key === 'avatar') {
document.querySelector('.prew').src = userObj[key]
} else if (key === 'gender') {
const gRadioList = document.querySelectorAll('.gender')
const gNum = userObj[key]
gRadioList[gNum].checked = true
} else {
document.querySelector(`.${key}`).value = userObj[key]
}
})
})
关键:
回显数据到标签上我们可以总结经验:使用forEach方法遍历Object.keys()方法得到的数组
Object.keys(userObj).forEach(key => {
document.querySelector(`.${key}`).value = userObj[key]
}
模块二:头像修改 借鉴案例一更换网站背景
document.querySelector('.upload').addEventListener('change', e => {
const fd = new FormData()
fd.append('avator', e.target.files[0])
fd.append('creator', creator)
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
})
})
模块三:提交表单 + 结果提示
document.querySelector('.submit').addEventListener('click', () => {
const userForm = document.querySelector('.user-form')
const userObj = serialize(userForm, { hash: true, empty: true })
userObj.creator = creator
//性别数字字符串转成数字类型
userObj.gender = +userObj.gender
axios({
url: 'http://hmajax.itheima.net/api/settings',
method: 'put',
data: userObj
}).then(result => {
const toastDom = document.querySelector('.my-toast')
const toast = new bootstrap.Toast(toastDom)
toast.show()
})
})
Bootstrap提示框
案例三:Promise + XHR获取省份列表
<script>
// 1. 创建Promise对象
const p = new Promise((resolve, reject) => {
// 2. 执行XHR异步代码,获取省份列表
const xhr = new XMLHttpRequest()
xhr.open('GET', 'http://hmajax.itheima.net/api/province')
xhr.addEventListener('loadend', () => {
// 2xx开头的都是成功响应状态码
if (xhr.status >= 200 && xhr.status < 300) {
resolve(JSON.parse(xhr.response))
} else {
reject(new Error(xhr.response))
}
})
xhr.send()
})
// 3. 关联成功或失败函数,做后续处理
p.then(result => {
console.log(result)
document.querySelector('.my-p').innerHTML = result.list.join('<br>')
}).catch(error => {
// 错误对象要用console.dir详细打印
console.dir(error)
document.querySelector('.my-p').innerHTML = error.message
})
</script>
注意:
1. 因为2xx开头的都是成功响应状态码,xhr由此判断响应成功还是失败
2. reject()里面的参数一般跟new Error()
3. 错误对象要用console.dir详细打印,里面需要的报错信息一般是error.message
案例四:天气预报
模块一:渲染函数
function getWeather(cityCode) {
myAxios({
url: 'http://hmajax.itheima.net/api/weather',
params: {
city: cityCode
}
}).then(result => {
//console.log(result)
const wObj = result.data
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
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('')
document.querySelector('.week-wrap').innerHTML = dayForecastStr
})
}
//默认进入网页就要获取天气数据
getWeather('110100')
模板字符串渲染各部分并修改标签内容
渲染小li时需要用map()和join()方法处理数组并且转化成字符串
模块二:搜索城市列表
document.querySelector('.search-city').addEventListener('input', (e) => {
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('')
document.querySelector('.search-list').innerHTML = liStr
})
})
渲染小li时需要用map()和join()方法处理数组并且转化成字符串
模块三:切换城市天气
document.querySelector('.search-list').addEventListener('click', (e) => {
if (e.target.classList.contains('city-item')) {
const cityCode = e.target.dataset.code
getWeather(cityCode)
}
})
注意:这里的小li是动态创建的,因此需要事件委托给父级绑定点击事件,通过给小li添加自定义属性获取渲染函数的参数
案例五:商品分类案例
<script>
// 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>
注意:
1.return的值可以是创建获取二级分类请求
2.返回的模板字符串可以用两次map()嵌套解决