前兩天寫了個置頂,并封裝成插件,體會了一遍自己封裝插件的過程,深有感觸。
完整代碼放在GitHub上:https://github.com/HiJackLi/demo/tree/master/
| 1.
第一就是封裝這種功能插件不能扯上外界樣式等等界面上的復雜要求,只提供主要功能即可,并且是具有普遍性,能夠應用到多種場景中去。
| 2.
第二,封裝函數(shù)的參數(shù)傳遞什么、如何傳遞問題:
參數(shù)傳遞如下:
function scroll(ele,scrollPosition,duration,interval){}
ele(針對哪個元素的滾動條滾動,默認是文檔自身滾動條滾動)
scrollPositon(滾動條滾動到哪,默認是文檔最頂部)
duration(滾動條滾動的總時間,默認1秒鐘)
interval(滾動條滾動的幀率,也就是每一幀運動時間)
如何傳遞:
如果就這樣傳遞也可以,但未免太過繁瑣,在參數(shù)較多的情況下,可以傳遞一個對象進去,把配置選項放在對象中傳遞,如下:
function scroll( option = {
ele: document.documentElement,
scrollPosition: 0,
duration: 1000,
interval: 16.7
} ){}
這樣,在功能調用時,如果沒穿,默認就是這些參數(shù)。
但是如果用戶傳遞了參數(shù),并且傳遞不全,那么這樣寫最后option對象的默認值就會被替代,最終起不到作用,所以這樣寫不行。如下引入Object.assign方法進行修改。
function scroll(option={}) {
defOption = {
ele: document.documentElement,
scrollPosition: 0,
interval: 16.7
}
var options = Object.assign(option,defOptions);
}
這樣不管用戶如何傳遞參數(shù),都能夠正常運行。
| 3.
第三,滾動條滾動需要依托setInterval計時器,但是還得知道每一幀運動的距離,如下是求運動的總距離、運動每一幀的距離的方程
總距離 = 目標距離 - 當前距離
幀距 = 總距離 / 總幀數(shù) = 總距離 / ( 總時間 / 幀率 )
所以代碼如下:
// 滾動功能部分
options.distance = options.targetScroll - options.ele.scrollTop; // 總距離
options.times = Math.ceil(options.duration / options.interval); // 總幀數(shù)
options.perDistance = options.distance / options.times; // 幀距
var curTimes = 0; // 聲明一個參數(shù)用于記載運動次數(shù)
var timer = setInterval(function () {
if (curTimes == options.times) {
clearInterval(timer);
}
options.ele.scrollTop += options.perDistance;
curTimes++;
}, options.interval);
如上,基本上功能就已經實現(xiàn)了。
| 4.
如果只做到上面這種可能一些功能就能實現(xiàn),但是遇到如下需求就不能夠實現(xiàn)了。
需求1:滾動之前置頂按鈕需要處理一些事情,希望等我處理完插件在進行滾動
需求2:同需求1,如果我要處理的事情是異步的,希望也能夠正常
解決需求1:只要把在傳參時設置一個回調函數(shù),并在插件適當位置執(zhí)行回調,比如在滾動定時器之前插入onscrollBefore() 如下:
// 頁面js
scroll({
onscrollBefore:function() {
// 同步操作
},
onscrollAfter:function() {
}
})
解決需求2:如果onscrollBefore中處理的操作是異步的,那么上面的回調做法并不能解決異步問題,比如等待3秒再滾動,那么點擊置頂按鈕時,滾動會立即執(zhí)行,并不會等待3秒,這原因是因為異步操作是要放在事件隊列中等待同步操作結束才能夠執(zhí)行的。那么,我們可以在onscrollBefore回調函數(shù)中再傳入一個參數(shù)start,用來控制插件是否執(zhí)行運動,也就是希望這個參數(shù)start把插件的運動能力掌握在自己手中,那么,插件就需要把運動功能部分封裝成一個函數(shù),這個函數(shù)就是start,代碼如下:
// 頁面js
scroll({
onscrollBefore:function(start) {
// 異步操作
setTimeout(()=>{
console.log("等待3秒打印完這句就執(zhí)行滾動!");
start();
},3000)
}
// 插件js
function scroll(){
onscrollBefore(start);
function start() {
// 運動功能部分封裝到這個start函數(shù)中
}
}
如上,就解決了異步處理問題。把控制權通過參數(shù)交給了用戶自己,讓用戶決定是否和何時滾動。