使用Fetch请求服务器响应时显示预加载元素的问题排查
问题:Fetch请求时预加载器无法显示
我在使用fetch请求数据时,没法在请求数据展示前看到预加载器。排查后发现showLoad和hideLoad函数逻辑看起来没问题,但loader元素就是不显示,该怎么解决?
HTML代码
<div class="conteinerInfo"> <div id="load"></div> </div>
CSS代码
#load{ border: 5px solid #f3f3f3; border-top: 5px solid #3498db; border-radius: 50%; width: 20px; height: 20px; animation: spin 2s linear infinite; margin-left: 160px; display: none; } #load.display{ display: block; } @keyframes spin { 0% { transform: rotate(0deg); } 100% { transform: rotate(360deg); } }
JavaScript代码
let searchButton = document.getElementById('button') let showInfo = document.getElementsByClassName('conteinerInfo') showInfo[0].setAttribute('id', 'mainddiv') let divId = document.getElementById('mainddiv') let loader = document.getElementById('load') function showLoad(){ loader.classList.add('display') } function hideLoad(){ loader.classList.remove('display') } function getWeather () { showLoad() fetch(`http://api.weatherapi.com/v1/current.json?key=XXXXXXX&q=${input.value}&aqi=no`) .then(response => response.json()) .then(res => { hideLoad() let celsius = 'Temp' + ' ' + res.current.temp_c + " " + '°C' divId.innerHTML = celsius }) } searchButton.addEventListener('click', getWeather)
问题原因及解决方法
- DOM被覆盖是核心问题
你给.conteinerInfo元素添加了mainddivID,之后用divId.innerHTML = celsius直接替换了该容器的所有内容——这会把里面的loader元素彻底删除。后续即使调用showLoad,也找不到这个loader元素了。
解决办法:
单独新增一个容器用于显示天气信息,让loader和天气信息容器处于同一层级:
- 修改HTML:
<div class="conteinerInfo"> <div id="load"></div> <div id="weather-content"></div> </div>
- 修改JS中更新内容的代码:
// 替换原来的divId.innerHTML = celsius document.getElementById('weather-content').innerHTML = celsius
- 可选:解决网络过快导致loader一闪而过的问题
如果本地网络极好,请求会瞬间完成,loader可能来不及显示。可以给hideLoad加个最小延迟,方便调试时看到效果:
.then(res => { setTimeout(() => { hideLoad() document.getElementById('weather-content').innerHTML = celsius }, 500) })
- 样式优先级兜底(非必要)
如果后续有其他样式意外覆盖loader的display属性,可以给.display类增加优先级:
#load.display{ display: block !important; }
内容的提问来源于stack exchange,提问作者willd
相关产品推荐
相关产品推荐

