【JavaScript】回调地狱以及网页轮播图底层分析

简介: 回调地狱以及网页轮播图底层分析

🏍️回调地狱

🍇具体分析

根据上文动画函数的讲解,今天更近一步加深对回调函数的使用

<!DOCTYPEhtml><htmllang="en"><head><metacharset="UTF-8"><metahttp-equiv="X-UA-Compatible"content="IE=edge"><metaname="viewport"content="width=device-width, initial-scale=1.0"><title>Document</title><style>div {
width: 200px;
height: 200px;
background: #f00;margin-top: 30px;
position: absolute;
        }
</style></head><body><button>测试按钮</button><div></div></body></html>

图片.png

通过页面的内容,我想让盒子一次性实现向左移动然后变宽然后变高然后向下移动然后向上移动,然后向左移动。。。 如何做???,这里我们就需要借助回调函数不断调用定时器移动,通俗点讲,我们讲多个回调函数一起使用称为“回调地狱”。

写JS第一步通常就是获取DOM元素,但是接下来的回调函数如何书写,请看如下代码及注释:

<script>varbtn=document.querySelector('button')
vardiv=document.querySelector('div')
functionmove (obj, attr, target, speed, callback) {
// 关闭上一个定时器clearInterval(obj.timer);
// 获取元素当前位置varcurrent=parseInt(getStyle(obj, attr));
// 判断速度的正负值if (current>target) {
// 此时速度应为负值speed=-speed;
        }
// 开启一个定时器,用来执行动画效果// 向执行动画的对象添加一个timer属性,用来保存它自己的定时器obj.timer=setInterval(function () {
// 获取目标原来的left值varoldValue=parseInt(getStyle(obj, attr));
// 在旧值的基础上增加varnewValue=oldValue+speed;
/*             向左移动时,需要判断newValue是否小于target            向右移动时,需要判断newValue是否大于target            */if ((speed<0&&newValue<target) || (speed>0&&newValue>target)) {
newValue=target;
            }
// 将新值赋予目标obj.style[attr] =newValue+'px';
// 当元素移动到target时,停止执行动画if (newValue==target) {
// 达到目标关闭定时器clearInterval(obj.timer);
// 动画执行完毕调用回调函数 callbackcallback&&callback();
            }
        }, 30);
    }
//定义一个函数,用来获取指定元素的当前样式functiongetStyle (obj, name) {
if (window.getComputedStyle) {
// 正常浏览器的方式,具有getComputedStyle()方法returngetComputedStyle(obj, null)[name];
        } else {
// IE8的方式,没有getComputedStyle()方法returnobj.currentStyle[name];
        }
    }
</script>

现在分别对代码里面的参数进行讲解:

   move参数:

   * obj:要执行动画的对象

   * attr:要执行动画的样式

   * target:执行动画的目标位置

   * speed:移动的速度(正数向右移,负数向左移)

   * callback:回调函数,这个函数将会在动画执行完毕以后执行

   getStyle参数:

   * obj:要获取样式的元素

   * name:要获取的样式名

定时器书写完毕,我们开始调用move函数,可以看到move里面的callback回调函数里面在嵌套move,接着在回调函数里面在嵌套move,不停的在callback里面嵌套函数,达到连续的动画效果,称为“回调函数”,可以看一下效果,如下:

btn.addEventListener('click', function () {
move(div, "left", 300, 10, function () {
move(div,"width",500,10,function() {
move(div,"height",300,10,function(){
move(div,"bottom",100,10,function(){
move(div,"top",100,10,function(){
move(div,"left",-200,10,function(){})
                    })
                })
            })
        })
    })
})

图片.png

通过画面可以看到非常丝滑的动画效果,在这我们就要思考一下,是否可以把这个动画函数封装在一个JS文件里,当我们想要实现动画效果时直接调用动画函数就可以了,答案是“可行的”。这样便于了代码的书写,大大提高了编程效率。接下来通过一个典型案例,在进行动画函数的学习。

🍈完整代码

<!DOCTYPEhtml><htmllang="en"><head><metacharset="UTF-8"><metahttp-equiv="X-UA-Compatible"content="IE=edge"><metaname="viewport"content="width=device-width, initial-scale=1.0"><title>Document</title><style>div {
width: 200px;
height: 200px;
background: #f00;margin-top: 30px;
position: absolute;
        }
</style></head><body><button>测试按钮</button><div></div><script>varbtn=document.querySelector('button')
vardiv=document.querySelector('div')
functionmove (obj, attr, target, speed, callback) {
// 关闭上一个定时器clearInterval(obj.timer);
// 获取元素当前位置varcurrent=parseInt(getStyle(obj, attr));
// 判断速度的正负值if (current>target) {
// 此时速度应为负值speed=-speed;
            }
// 开启一个定时器,用来执行动画效果// 向执行动画的对象添加一个timer属性,用来保存它自己的定时器obj.timer=setInterval(function () {
// 获取目标原来的left值varoldValue=parseInt(getStyle(obj, attr));
// 在旧值的基础上增加varnewValue=oldValue+speed;
/*                 向左移动时,需要判断newValue是否小于target                向右移动时,需要判断newValue是否大于target                */if ((speed<0&&newValue<target) || (speed>0&&newValue>target)) {
newValue=target;
                }
// 将新值赋予目标obj.style[attr] =newValue+'px';
// 当元素移动到target时,停止执行动画if (newValue==target) {
// 达到目标关闭定时器clearInterval(obj.timer);
// 动画执行完毕调用回调函数 callbackcallback&&callback();
                }
            }, 30);
        }
functiongetStyle (obj, name) {
if (window.getComputedStyle) {
// 正常浏览器的方式,具有getComputedStyle()方法returngetComputedStyle(obj, null)[name];
            } else {
// IE8的方式,没有getComputedStyle()方法returnobj.currentStyle[name];
            }
        }
btn.addEventListener('click', function () {
move(div, "left", 300, 10, function () {
move(div,"width",500,10,function() {
move(div,"height",300,10,function(){
move(div,"bottom",100,10,function(){
move(div,"top",100,10,function(){
move(div,"left",-200,10,function(){})
                            })
                        })
                    })
                })
            })
        })
</script></body></html>

🏃网页轮播

轮播图也称为焦点图,是网页中比较常见的特效,今天做一下这个典型案例。

🍉制作轮播图的空间盒子,用来存放图片

我们可以根据自己的喜好设置自己轮播图的相关样式,这里就就需要借助HTML和CSS了,讲真HTML和CSS是重点基础,如果这两个没学好,是制作不出自己想要的样式,更别提后面的JS以及相关框架了,基础才是最重要的。

<!DOCTYPEhtml><htmllang="en"><head><metacharset="UTF-8"><metahttp-equiv="X-UA-Compatible"content="IE=edge"><metaname="viewport"content="width=device-width, initial-scale=1.0"><title>Document</title><style>*{
margin: 0;
padding: 0;
        }
/* 设置outer样式 */#outer{/* 设置宽高 */width: 820px;
height: 452px;
/* 居中 */margin: 50pxauto;
/* 设置背景颜色 */background-color: #008c8c;/* 设置padding */padding: 10px0;
/* 开启相对定位 */position: relative;
/* 溢出隐藏 */overflow: hidden;
        }
/* 设置imgList */#imgList{/* 去除项目符号 */list-style: none;
/* 设置ul宽度 *//* width: 3280px; *//* 开启绝对定位 */position: absolute;
/* 设置偏移量,每向左移动820px 就会显示下一张图片 */        }
/* 设置li */#imgList li{/* 设置浮动 */float: left;
/* 设置左右外边距 */margin: 010px;
        }
/* 设置导航按钮 */        .navDiv{
/* 开启绝对定位 */position: absolute;
/* 设置位置 */bottom: 20px;
/* left: 35%; */        }
        .navDiva{
/* 设置浮动,浮动之后,行内元素就能设置宽高 */float: left;
/* 设置宽高 */width: 25px;
height: 25px;
/* 设置背景颜色 */background-color: #f00;/* 设置左右外边距 */margin: 015px;
/* 设置半透明 */opacity: .5;
/* 设置圆角 */border-radius: 50%;
        }
/* 设置鼠标移入效果 */        .navDiva:hover{
background-color: green;
        }
</style></head><body><!--创建一个外部的div作为一个大的容器--><divid="outer"><!--创建一个ul,用于放置图片--><ulid="imgList"><li><imgsrc="./01.jpeg"></li><li><imgsrc="./02.jpeg"></li><li><imgsrc="./03.jpeg"></li><li><imgsrc="./04.jpeg"></li><li><imgsrc="./01.jpeg"></li></ul><!--设置导航按钮--><divclass="navDiv"><ahref="javascript:;"></a><ahref="javascript:;"></a><ahref="javascript:;"></a><ahref="javascript:;"></a></div></div></body></html>

图片.png

图片.png

这里需要注意两点:


轮播图的按钮是要通过JS来居中,因为如果借助CSS居中,就会写死,后期添加图片又要重新设置。

javascript:;是一个伪协议,加在超级链接上就可以防止 链接跳转,从而可以给链接JS上写自己想执行的代码。javascript:void(0) 表示一个死链接,执行空事件。

🍊点击小圆圈可以播放相应的图片

<script>window.addEventListener('load',function(){
// 获取ul标签varul=document.querySelector('#imgList')
// 获取ul下li的子元素的个数,并给ul动态赋予宽度值ul.style.width=ul.children.length*820+'px';
// 设置导航按钮动态居中varnavDiv=document.querySelector('.navDiv');
varouter=document.querySelector('#outer');
navDiv.style.left= (outer.offsetWidth-navDiv.offsetWidth) /2+'px';
// 默认显示图片的索引varindex=0;
// 获取所有的avaraAll=document.querySelector('.navDiv').querySelectorAll('a');
// 为所有超链接绑定响应函数for(vari=0;i<aAll.length;i++){
// 为每一个超链接都添加一个num属性aAll[i].num=i;
// 为超链接绑定点击响应函数aAll[i].addEventListener('click',function(){
// 获取超链接的索引,并将其设置为indexindex=this.num;
// 切换图片imgList.style.left=-820*index+'px';
setA();
            })
        }
// 创建一个方法用来选中afunctionsetA(){
for(vari=0;i<aAll.length;i++){
aAll[i].style.backgroundColor='';
            }
// 创建点击时的颜色aAll[index].style.backgroundColor='green';
        }   
    })
</script>

通过JS书写动态给按钮进行居中,并设置一个点击事件,来进行图片的切换并且按钮样式虽图片的变化而变化,这里借用了“排他思想”,先干掉所有人,然后保留自己人。

图片.png

🍋鼠标不点击,轮播图会自动播放

自动播放就涉及动画函数了,根据上文的回调地狱的讲解,将动画函数move进行封装。如下:

functionmove(obj,attr,target,speed,callback){
// 关闭上一个定时器clearInterval(obj.timer);
// 获取元素当前位置varcurrent=parseInt(getStyle(obj,attr));
// 判断速度的正负值if(current>target){
// 此时速度应为负值speed=-speed;
    }
// 开启一个定时器,用来执行动画效果// 向执行动画的对象添加一个timer属性,用来保存它自己的定时器obj.timer=setInterval(function(){
// 获取目标原来的left值varoldValue=parseInt(getStyle(obj,attr));
// 在旧值的基础上增加varnewValue=oldValue+speed;
/*         向左移动时,需要判断newValue是否小于target        向右移动时,需要判断newValue是否大于target        */if((speed<0&&newValue<target) || (speed>0&&newValue>target)){
newValue=target;
        }
// 将新值赋予目标obj.style[attr] =newValue+'px';
// 当元素移动到target时,停止执行动画if(newValue==target){
// 达到目标关闭定时器clearInterval(obj.timer);
// 动画执行完毕调用回调函数 callbackcallback&&callback();
        }
    },30);
}
functiongetStyle(obj,name){
if(window.getComputedStyle){
// 正常浏览器的方式,具有getComputedStyle()方法returngetComputedStyle(obj,null)[name];
    }else{
// IE8的方式,没有getComputedStyle()方法returnobj.currentStyle[name];
    }
}

接下里通过引入move函数实现动画效果

<script>window.addEventListener('load',function(){
// 获取ul标签varul=document.querySelector('#imgList')
// 获取ul下li的子元素的个数,并给ul动态赋予宽度值ul.style.width=ul.children.length*820+'px';
// 设置导航按钮动态居中varnavDiv=document.querySelector('.navDiv');
varouter=document.querySelector('#outer');
navDiv.style.left= (outer.offsetWidth-navDiv.offsetWidth) /2+'px';
// 默认显示图片的索引varindex=0;
// 获取所有的avaraAll=document.querySelector('.navDiv').querySelectorAll('a');
// 设置默认选中效果aAll[index].style.backgroundColor='green';
// 为所有超链接绑定响应函数for(vari=0;i<aAll.length;i++){
// 为每一个超链接都添加一个num属性aAll[i].num=i;
// 为超链接绑定点击响应函数aAll[i].addEventListener('click',function(){
//关闭自动切换的定时器clearInterval(stop);
// 获取超链接的索引,并将其设置为indexindex=this.num;
// 切换图片// imgList.style.left = -820*index + 'px';setA();
move(imgList,"left",-820*index,20,function(){
//动画执行完毕,开启自动切换autoChange();
                })
            })
        }
// // 开启自动切换图片autoChange();
// 创建一个方法用来选中afunctionsetA(){
// 判断当前索引是否是第一张if(index>=ul.children.length-1){
// 则将index设置为0index=0;
// 此时显示最后一张图片,而最后一张图片和第一张一模一样// 通过CSS将最后一张切换成第一张imgList.style.left=0+'px';
            }
for(vari=0;i<aAll.length;i++){
aAll[i].style.backgroundColor='';
            }
// 创建点击时的颜色aAll[index].style.backgroundColor='green';
        }   
// 创建一个函数,用来开启自动切换图片// 定义一个自动切换的定时器的标识varstop;
functionautoChange(){
// 开启一个定时器,用来定时切换图片stop=setInterval(function(){
// 使索引自增index++;
// 判断index的值index%=ul.children.length;
// 执行动画来切换图片move(imgList,"left",-820*index,20,function(){
// 设置导航点setA();
                })
            },3000);
        };
    })
</script><scriptsrc="./move.js"></script>

可以看到代码中,我们设计了一个定时器实现自动切换图片,并设计在点击函数中关闭定时器,这样就不会出现点击事件和自动播放发生冲突,造成图片的怪异播放现象。

🍌完整代码

<!DOCTYPEhtml><htmllang="en"><head><metacharset="UTF-8"><metahttp-equiv="X-UA-Compatible"content="IE=edge"><metaname="viewport"content="width=device-width, initial-scale=1.0"><title>Document</title><style>*{
margin: 0;
padding: 0;
        }
/* 设置outer样式 */#outer{/* 设置宽高 */width: 820px;
height: 452px;
/* 居中 */margin: 50pxauto;
/* 设置背景颜色 */background-color: #008c8c;/* 设置padding */padding: 10px0;
/* 开启相对定位 */position: relative;
/* 溢出隐藏 */overflow: hidden;
        }
/* 设置imgList */#imgList{/* 去除项目符号 */list-style: none;
/* 设置ul宽度 *//* width: 3280px; *//* 开启绝对定位 */position: absolute;
/* 设置偏移量,每向左移动820px 就会显示下一张图片 */        }
/* 设置li */#imgList li{/* 设置浮动 */float: left;
/* 设置左右外边距 */margin: 010px;
        }
/* 设置导航按钮 */        .navDiv{
/* 开启绝对定位 */position: absolute;
/* 设置位置 */bottom: 20px;
/* left: 35%; */        }
        .navDiva{
/* 设置浮动,浮动之后,行内元素就能设置宽高 */float: left;
/* 设置宽高 */width: 25px;
height: 25px;
/* 设置背景颜色 */background-color: #f00;/* 设置左右外边距 */margin: 015px;
/* 设置半透明 */opacity: .5;
/* 设置圆角 */border-radius: 50%;
        }
/* 设置鼠标移入效果 */        .navDiva:hover{
background-color: green;
        }
</style><script>window.addEventListener('load',function(){
// 获取ul标签varul=document.querySelector('#imgList')
// 获取ul下li的子元素的个数,并给ul动态赋予宽度值ul.style.width=ul.children.length*820+'px';
// 设置导航按钮动态居中varnavDiv=document.querySelector('.navDiv');
varouter=document.querySelector('#outer');
navDiv.style.left= (outer.offsetWidth-navDiv.offsetWidth) /2+'px';
// 默认显示图片的索引varindex=0;
// 获取所有的avaraAll=document.querySelector('.navDiv').querySelectorAll('a');
// 设置默认选中效果aAll[index].style.backgroundColor='green';
// 为所有超链接绑定响应函数for(vari=0;i<aAll.length;i++){
// 为每一个超链接都添加一个num属性aAll[i].num=i;
// 为超链接绑定点击响应函数aAll[i].addEventListener('click',function(){
//关闭自动切换的定时器clearInterval(stop);
// 获取超链接的索引,并将其设置为indexindex=this.num;
// 切换图片// imgList.style.left = -820*index + 'px';setA();
move(imgList,"left",-820*index,20,function(){
//动画执行完毕,开启自动切换autoChange();
                    })
                })
            }
// // 开启自动切换图片autoChange();
// 创建一个方法用来选中afunctionsetA(){
// 判断当前索引是否是第一张if(index>=ul.children.length-1){
// 则将index设置为0index=0;
// 此时显示最后一张图片,而最后一张图片和第一张一模一样// 通过CSS将最后一张切换成第一张imgList.style.left=0+'px';
                }
for(vari=0;i<aAll.length;i++){
aAll[i].style.backgroundColor='';
                }
// 创建点击时的颜色aAll[index].style.backgroundColor='green';
            }   
// 创建一个函数,用来开启自动切换图片// 定义一个自动切换的定时器的标识varstop;
functionautoChange(){
// 开启一个定时器,用来定时切换图片stop=setInterval(function(){
// 使索引自增index++;
// 判断index的值index%=ul.children.length;
// 执行动画来切换图片move(imgList,"left",-820*index,20,function(){
// 设置导航点setA();
                    })
                },3000);
            };
        })
</script><scriptsrc="./tool.js"></script></head><body><!--创建一个外部的div作为一个大的容器--><divid="outer"><!--创建一个ul,用于放置图片--><ulid="imgList"><li><imgsrc="./01.jpeg"></li><li><imgsrc="./02.jpeg"></li><li><imgsrc="./03.jpeg"></li><li><imgsrc="./04.jpeg"></li><li><imgsrc="./01.jpeg"></li></ul><!--设置导航按钮--><divclass="navDiv"><ahref="javascript:;"></a><ahref="javascript:;"></a><ahref="javascript:;"></a><ahref="javascript:;"></a></div></div></body></html>


相关文章
|
12天前
|
Web App开发 监控 JavaScript
监控和分析 JavaScript 内存使用情况
【10月更文挑战第30天】通过使用上述的浏览器开发者工具、性能分析工具和内存泄漏检测工具,可以有效地监控和分析JavaScript内存使用情况,及时发现和解决内存泄漏、过度内存消耗等问题,从而提高JavaScript应用程序的性能和稳定性。在实际开发中,可以根据具体的需求和场景选择合适的工具和方法来进行内存监控和分析。
|
30天前
|
存储 JavaScript 前端开发
使用JavaScript构建动态交互式网页:从基础到实践
【10月更文挑战第12天】使用JavaScript构建动态交互式网页:从基础到实践
69 1
|
2月前
|
编解码 前端开发 JavaScript
javascript检测网页缩放演示代码
javascript检测网页缩放演示代码
|
8天前
|
运维 监控 JavaScript
鸿蒙next版开发:分析JS Crash(进程崩溃)
在HarmonyOS 5.0中,JS Crash指未处理的JavaScript异常导致应用意外退出。本文详细介绍如何分析JS Crash,包括异常捕获、日志分析和典型案例,帮助开发者定位问题、修复错误,提升应用稳定性。通过DevEco Studio收集日志,结合HiChecker工具,有效解决JS Crash问题。
25 4
|
11天前
|
JavaScript
js实现简洁实用的网页计算器功能源码
这是一款使用js实现简洁实用的网页计算器功能源码。可实现比较基本的加减乘除四则运算功能,界面简洁实用,是一款比较基本的js运算功能源码。该源码可兼容目前最新的各类主流浏览器。
20 2
|
17天前
|
Web App开发 JavaScript 前端开发
使用 Chrome 浏览器的内存分析工具来检测 JavaScript 中的内存泄漏
【10月更文挑战第25天】利用 Chrome 浏览器的内存分析工具,可以较为准确地检测 JavaScript 中的内存泄漏问题,并帮助我们找出潜在的泄漏点,以便采取相应的解决措施。
116 9
|
1月前
|
存储 JavaScript 前端开发
【JavaScript】网页交互的灵魂舞者
本文介绍了 JavaScript 的三种引入方式(行内、内部、外部)和基础语法,包括变量、数据类型、运算符、数组、函数和对象等内容。同时,文章还详细讲解了 jQuery 的基本语法和常用方法,如 `text()`、`html()`、`val()`、`attr()` 和 `css()` 等,以及如何插入和删除元素。通过示例代码和图解,帮助读者更好地理解和应用这些知识。
15 1
【JavaScript】网页交互的灵魂舞者
|
15天前
|
JavaScript 前端开发 开发者
前端框架对比:Vue.js与Angular的优劣分析与选择建议
【10月更文挑战第27天】在前端开发领域,Vue.js和Angular是两个备受瞩目的框架。本文对比了两者的优劣,Vue.js以轻量级和易上手著称,适合快速开发小型到中型项目;Angular则由Google支持,功能全面,适合大型企业级应用。选择时需考虑项目需求、团队熟悉度和长期维护等因素。
21 1
|
16天前
|
JavaScript 前端开发 API
前端框架对比:Vue.js与Angular的优劣分析与选择建议
【10月更文挑战第26天】前端技术的飞速发展让开发者在构建用户界面时有了更多选择。本文对比了Vue.js和Angular两大框架,介绍了它们的特点和优劣,并给出了在实际项目中如何选择的建议。Vue.js轻量级、易上手,适合小型项目;Angular结构化、功能强大,适合大型项目。
16 1
|
1月前
|
前端开发
js-基础轮播图制作
js-基础轮播图制作
24 7