案例总结【原生js置顶插件】
前两天写了个置顶,并封装成插件,体会了一遍自己封装插件的过程,深有感触。
完整代码放在GitHub上:https://github.com/HiJackLi/demo/tree/master/
| 1.
第一就是封装这种功能插件不能扯上外界样式等等界面上的复杂要求,只提供主要功能即可,并且是具有普遍性,能够应用到多种场景中去。
| 2.
第二,封装函数的参数传递什么、如何传递问题:
参数传递如下:
function scroll(ele,scrollPosition,duration,interval){}
ele(针对哪个元素的滚动条滚动,默认是文档自身滚动条滚动)
scrollPositon(滚动条滚动到哪,默认是文档最顶部)
duration(滚动条滚动的总时间,默认1秒钟)
interval(滚动条滚动的帧率,也就是每一帧运动时间)
如何传递:
如果就这样传递也可以,但未免太过繁琐,在参数较多的情况下,可以传递一个对象进去,把配置选项放在对象中传递,如下:
function scroll( option = {
ele: document.documentElement,
scrollPosition: 0,
duration: 1000,
interval: 16.7
} ){}
这样,在功能调用时,如果没穿,默认就是这些参数。
但是如果用户传递了参数,并且传递不全,那么这样写最后option对象的默认值就会被替代,最终起不到作用,所以这样写不行。如下引入Object.assign方法进行修改。
function scroll(option={}) {
defOption = {
ele: document.documentElement,
scrollPosition: 0,
interval: 16.7
}
var options = Object.assign(option,defOptions);
}
这样不管用户如何传递参数,都能够正常运行。
| 3.
第三,滚动条滚动需要依托setInterval计时器,但是还得知道每一帧运动的距离,如下是求运动的总距离、运动每一帧的距离的方程
总距离 = 目标距离 - 当前距离
帧距 = 总距离 / 总帧数 = 总距离 / ( 总时间 / 帧率 )
所以代码如下:
// 滚动功能部分
options.distance = options.targetScroll - options.ele.scrollTop; // 总距离
options.times = Math.ceil(options.duration / options.interval); // 总帧数
options.perDistance = options.distance / options.times; // 帧距
var curTimes = 0; // 声明一个参数用于记载运动次数
var timer = setInterval(function () {
if (curTimes == options.times) {
clearInterval(timer);
}
options.ele.scrollTop += options.perDistance;
curTimes++;
}, options.interval);
如上,基本上功能就已经实现了。
| 4.
如果只做到上面这种可能一些功能就能实现,但是遇到如下需求就不能够实现了。
需求1:滚动之前置顶按钮需要处理一些事情,希望等我处理完插件在进行滚动
需求2:同需求1,如果我要处理的事情是异步的,希望也能够正常
解决需求1:只要把在传参时设置一个回调函数,并在插件适当位置执行回调,比如在滚动定时器之前插入onscrollBefore() 如下:
// 页面js
scroll({
onscrollBefore:function() {
// 同步操作
},
onscrollAfter:function() {
}
})
解决需求2:如果onscrollBefore中处理的操作是异步的,那么上面的回调做法并不能解决异步问题,比如等待3秒再滚动,那么点击置顶按钮时,滚动会立即执行,并不会等待3秒,这原因是因为异步操作是要放在事件队列中等待同步操作结束才能够执行的。那么,我们可以在onscrollBefore回调函数中再传入一个参数start,用来控制插件是否执行运动,也就是希望这个参数start把插件的运动能力掌握在自己手中,那么,插件就需要把运动功能部分封装成一个函数,这个函数就是start,代码如下:
// 页面js
scroll({
onscrollBefore:function(start) {
// 异步操作
setTimeout(()=>{
console.log("等待3秒打印完这句就执行滚动!");
start();
},3000)
}
// 插件js
function scroll(){
onscrollBefore(start);
function start() {
// 运动功能部分封装到这个start函数中
}
}
如上,就解决了异步处理问题。把控制权通过参数交给了用户自己,让用户决定是否和何时滚动。
发表评论 (审核通过后显示评论):