原生js封裝一個下拉加載的小組件

之前在面試的時候瓜晤,有些公司直接問我寫過什么組件,而當時的我的回答是:封裝ajax腹纳,封裝事件處理(兼容性)痢掠,前端路由,這些方法組件嘲恍,而并沒有一個比如下拉加載足画,輪播,加載中蛔钙,拖拽這樣的配合css以及js的這種組件锌云。當時最后的結果就是現(xiàn)場思考:一個輪播組件荠医,該有哪些方法吁脱,應該暴露什么方法桑涎,暴露什么屬性。所以最近靜下心來兼贡,也剛好在自己做的一個前后端分離的小項目中用到了下拉加載攻冷,就順帶把這個給抽離出來。記錄一下寫組件的過程遍希,希望能夠加深自己的感悟等曼。

下拉加載的實現(xiàn)原理

下拉加載的原理其實并不復雜,實現(xiàn)方法也有很多種凿蒜,這里我采用設置margin-top為負值禁谦,監(jiān)聽touchmove或者mousemove事件來檢測手指或者鼠標的位移,從而移動margin-top废封,在達到下拉閾值之后州泊,touchend或者mouseup事件進行回調函數(shù)的處理。從而完成重新加載漂洋。原理很簡單遥皂,但是在我實現(xiàn)的過程中,還是碰到了不少問題刽漂。下面一一說明演训。

具體的實現(xiàn)

按照需求驅動型的思路,我要新建一個上拉加載類贝咙,這個類應該至少具有兩個方法:

  1. start:通過這個方法样悟,上拉加載啟動。
  2. remove:通過這個方法庭猩,移除上拉加載相關事件乌奇。
    同時,需要有一些參數(shù):
  3. content:在哪個元素上下拉進行加載
  4. callback: 當下拉加載觸發(fā)的時候要進行什么樣的回調
  5. ptr: 顯示下拉的loading的元素
    根據(jù)上述的說法眯娱,大致的結構應該是這樣:
var callback
var pullreload = function(options){
    this.content = options.content;//目標下拉元素
    callback = options.callback || (default自己設計一個默認的回調)//下拉觸發(fā)后的回調
   this.ptr = options.ptr礁苗;
    this.start = function(){}//綁定事件
    this.remove = function(){} //清除綁定
}

可以看到,上述callback定義在外部徙缴,這是因為touchened,mouseup這些事件中需要對其進行操作试伙,定義在內部,一方面是事件回調不好進行訪問于样,另一方面疏叨,用戶能夠通過this.callback進行訪問,這個可以有穿剖,但是我并不希望用戶能夠通過這樣的方式修改callback蚤蔓,將其放在外部,除了內部函數(shù)糊余,沒有別人可以訪問到秀又,能夠私有這個變量单寂,達到私有的效果。事實上吐辙,個人感覺宣决,用原生js寫組件的話,有些方法需要放在外部昏苏,而有些方法需要放在屬性尊沸,有些方法放在prototype上。這些取決于實際的應用贤惯,不希望實例訪問洼专,當然是放在外部合適,而希望每一個實例都擁有孵构,放在屬性上更合適壶熏,而公用的方法,適合放在原型上浦译。最后棒假,外部通過立即執(zhí)行函數(shù)包裹或者webpack等工具進行打包,都可以避免外部私有變量污染全局精盅。
除了上述變量帽哑,還定義了一些私有變量以及方法,最終的代碼框架如下:

//檢測是否正在拉動,start設為true,end設為false叹俏,防止移動二次滑動產(chǎn)生干擾
var isDragging = false;
//是否達到閾值妻枕,下拉到一定程度之后,為true,否則為false
var isThresholdReached = false;
//記錄下拉初始鼠標位置
var popStart = 0;
//設置初始閾值
var threshold = 20;
//記錄上一次end回調是否執(zhí)行完畢
var isend = true;
//記錄當前是否處于最頂端
var isTop = true;

function getheight(event) {
   //通過event獲取高度粘驰,因為pc端和移動端不同屡谐,單獨寫一個方法來解決兼容問題
};
function movestart(event){
  //記錄初始位置,判斷是否位于頂端
}
function moving(event){
  //檢測滑動方向蝌数,進行相應的位移
}
function moveend(){
  //檢測是否達到下拉閾值愕掏,達到則進行回調,否則恢復初始狀態(tài)
}
var callback;
var pullReload = function(options){
  this.content = document.getElementById(options.content);
  this.ptr = document.getElementById('ptr');
  callback = options.callback || function(){};
  this.start = function(){
    //綁定事件
  }
  this.remove = function(){
    //移除事件
  }
  return this;
}
export default pullReload;

源碼見這里,里面是js和css分開寫的顶伞,最后通過webpack進行一個打包從而完成組件化饵撑。

碰到的問題

  1. content加載好之后,start中應該進行所有事件(touchmove)的綁定還是當touchstart或者mousedown之后進行事件的綁定唆貌?
    這里的話滑潘,有幾個考慮,一方面锨咙,touchmove觸發(fā)頻率特別快语卤,一直綁定給的話,對資源浪費很大,另一方面粹舵,touchmove并不需要實時綁定钮孵,因為當touchstart之后,如果此時并不處于最頂端齐婴,那么touchmove是完全不需要觸發(fā)的油猫,基于上述兩點稠茂,我對touchmove,touchend事件的綁定在touchstart中當檢測到用戶處于最頂端的時候進行綁定柠偶。
  2. event.preventDefault(),主要在touchmove事件中存在問題,因為touchmove事件的默認行為是滾動,如果不進行event.preventDefault()事件,那么在最頂部的時候澜掩,用戶下拉造成滾動叼耙,那么此時滾動條會發(fā)生一些奇怪的行為,進而導致檢測到的用戶觸摸點的位置發(fā)生偏差类茂,從而導致閾值的不正確觸發(fā)。而如果執(zhí)行event.preventDefault()的話,又會帶來另外一個問題摇邦,當用戶處于最頂端的時候,上拉屎勘,因為event,preventDefault()又帶來另一個問題施籍,拉不動了,這個時候用戶無法上拉概漱。很尷尬丑慎,迫于無奈,我最終的解決方案是在touchmove中進行一個上拉下拉的檢測瓤摧,上拉就不禁止默認竿裂,下拉禁止默認行為。從而解決了這個問題照弥。
  3. touchmove,touchend事件綁定在content元素上還是document上腻异?
    這里主要是因為用戶有可能在電腦上一滑,滑出了content的范圍这揣,就會導致touchmove,touchend沒有觸發(fā)捂掰,進而帶來一系列的問題,所以穩(wěn)妥起見曾沈,我綁定在了document上这嚣,當然,因為只有在最頂端的時候才會綁定個塞俱,所以性能上的損耗其實并不大姐帚,并不會影響用戶非下拉狀態(tài)下的體驗。

小結

組件的考慮障涯,其實還是在暴露的方法罐旗、屬性膳汪,以及私有的方法,屬性上的取舍九秀,根據(jù)具體的情況進行取舍遗嗽,才能上組件更加通用,可靠度更高鼓蜒。個人認為:不希望實例訪問痹换,當然是放在外部進行私有更合適,而希望每一個實例都擁有都弹,放在屬性上更合適娇豫,而公用的需要暴露的方法,適合放在原型上畅厢。
下一步的計劃希望能將這個小小的組件放到npm上冯痢,之前也一直沒有試過,用來體驗一把npm install還是很好玩的框杜。

最后編輯于
?著作權歸作者所有,轉載或內容合作請聯(lián)系作者
  • 序言:七十年代末浦楣,一起剝皮案震驚了整個濱河市,隨后出現(xiàn)的幾起案子咪辱,更是在濱河造成了極大的恐慌振劳,老刑警劉巖,帶你破解...
    沈念sama閱讀 206,378評論 6 481
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件梧乘,死亡現(xiàn)場離奇詭異澎迎,居然都是意外死亡,警方通過查閱死者的電腦和手機选调,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 88,356評論 2 382
  • 文/潘曉璐 我一進店門夹供,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人仁堪,你說我怎么就攤上這事哮洽。” “怎么了弦聂?”我有些...
    開封第一講書人閱讀 152,702評論 0 342
  • 文/不壞的土叔 我叫張陵鸟辅,是天一觀的道長。 經(jīng)常有香客問我莺葫,道長匪凉,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 55,259評論 1 279
  • 正文 為了忘掉前任捺檬,我火速辦了婚禮再层,結果婚禮上,老公的妹妹穿的比我還像新娘。我一直安慰自己聂受,他們只是感情好蒿秦,可當我...
    茶點故事閱讀 64,263評論 5 371
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著蛋济,像睡著了一般棍鳖。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上碗旅,一...
    開封第一講書人閱讀 49,036評論 1 285
  • 那天渡处,我揣著相機與錄音,去河邊找鬼扛芽。 笑死骂蓖,一個胖子當著我的面吹牛积瞒,可吹牛的內容都是我干的川尖。 我是一名探鬼主播,決...
    沈念sama閱讀 38,349評論 3 400
  • 文/蒼蘭香墨 我猛地睜開眼茫孔,長吁一口氣:“原來是場噩夢啊……” “哼叮喳!你這毒婦竟也來了?” 一聲冷哼從身側響起缰贝,我...
    開封第一講書人閱讀 36,979評論 0 259
  • 序言:老撾萬榮一對情侶失蹤馍悟,失蹤者是張志新(化名)和其女友劉穎,沒想到半個月后剩晴,有當?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體锣咒,經(jīng)...
    沈念sama閱讀 43,469評論 1 300
  • 正文 獨居荒郊野嶺守林人離奇死亡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內容為張勛視角 年9月15日...
    茶點故事閱讀 35,938評論 2 323
  • 正文 我和宋清朗相戀三年赞弥,在試婚紗的時候發(fā)現(xiàn)自己被綠了毅整。 大學時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點故事閱讀 38,059評論 1 333
  • 序言:一個原本活蹦亂跳的男人離奇死亡绽左,死狀恐怖悼嫉,靈堂內的尸體忽然破棺而出,到底是詐尸還是另有隱情拼窥,我是刑警寧澤戏蔑,帶...
    沈念sama閱讀 33,703評論 4 323
  • 正文 年R本政府宣布,位于F島的核電站鲁纠,受9級特大地震影響总棵,放射性物質發(fā)生泄漏。R本人自食惡果不足惜改含,卻給世界環(huán)境...
    茶點故事閱讀 39,257評論 3 307
  • 文/蒙蒙 一情龄、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧,春花似錦刃唤、人聲如沸隔心。這莊子的主人今日做“春日...
    開封第一講書人閱讀 30,262評論 0 19
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽硬霍。三九已至,卻和暖如春笼裳,著一層夾襖步出監(jiān)牢的瞬間唯卖,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 31,485評論 1 262
  • 我被黑心中介騙來泰國打工躬柬, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留拜轨,地道東北人。 一個月前我還...
    沈念sama閱讀 45,501評論 2 354
  • 正文 我出身青樓允青,卻偏偏與公主長得像橄碾,于是被迫代替她去往敵國和親。 傳聞我的和親對象是個殘疾皇子颠锉,可洞房花燭夜當晚...
    茶點故事閱讀 42,792評論 2 345

推薦閱讀更多精彩內容

  • Android 自定義View的各種姿勢1 Activity的顯示之ViewRootImpl詳解 Activity...
    passiontim閱讀 171,506評論 25 707
  • 極限特工2.10號凌晨首映法牲,我拉著朋友從八點等到12點。現(xiàn)在剛觀完影回來琼掠,內心還沒有從大片里出來... 這部電影的...
    好的唐詩閱讀 350評論 0 2
  • 從小就不擅長寫文章的我也明白多寫有好處拒垃。因為閱讀量少,進而寫作詞匯也達不到瓷蛙。文章中的方法我感覺太形式化悼瓮,不過可以嘗...
    李陽_98d1閱讀 134評論 0 0
  • 還依稀記得高三那年,盡管辛苦艰猬,但是只要想到大學那種開放的生活就會充滿精神横堡,在高中最喜歡的就是去操場跑步,放空一...
    Micon閱讀 282評論 0 0