一、 基礎實現 (1)功能
對 better-scroll 插件的基本封裝,實現移動端的滾動(2)實現 引入
better-scroll
props
probeType: better-scroll 配置項之一
(1)取值: 1 滾動的時候會派發 scroll 事件,會截流。 2 滾動的時候實時派發 scroll 事件,不會截流。 3 除了實時派發 scroll 事件,在 swipe 的情況下仍然能實時派發 scroll 事件。 (2)默認值:1
click: 點擊事件是否生效
refreshDelay: refresh事件的延遲時間
listenScroll: 是否監聽滾動事件,如果監聽滾動事件,則父組件應當給自定義事件‘onscroll’綁定監聽函數
data: 用于控制 scroll 刷新重新計算高度的數據
用于外部調用的方法enable()
disable()
refresh()
scrollTo(x, y, time, [easing])
easing取值只能為 swipe/swipeBounce/bounce
scrollToElement(el, time, [offsetX], [offsetY], [easing])
offsetX,offsetY為number或true,true表示滾動到目標元素中心位置,數值則為設置滾動到目標元素的偏移量思想步驟
在 mounted 鉤子中,在 $nextTick() 的回調中初始化 scroll 實例。
因為 scroll 實例初始化的時候必須保證其掛載對象(wrapper)的 DOM 已經渲染完成,由于 wrapper 中的數據可能異步獲取的,因此必須放在 $nextTick() 中,獲取更新數據后的 DOM,進行高度計算
watch父組件傳入的數據 data
DOM 上的數據發生了變化,要獲取更新后的 DOM ,在操作函數中同樣要在$nextTick()的回調中進行 scroll 的刷新,refresh 重新計算高度。此處 setTimeout() 與 $nextTick() 作用相同。
二、問題歸總 (1)與父組件交互問題
父組件中 scroll 下內容必須被包裹,不可出現如下結構。
......
父組件對 srcoll 組件方法的調用、dom 的操作
...
調用 scroll 中的方法:this.$refs.scrollName.methodName() 操作 dom(如改寫style): this.$refs.scrollName.$el.style
父組件引用 scroll 組件時 v-if 與 v-show 對其的影響
比如在 player.vue 組件中有如下結構。子組件 scroll 處在含有 v-show 屬性來 控制顯示的元素中。 1.v-if 與 v-show 的區別:v-if 會適當銷毀和重建組件,且只有條件為真時才會進 行渲染。v-show 則在整個父組件創建時就渲染,只是根據條件改寫元素的 css 屬性 display 的值來控制顯示與否。 2.當 scroll 在 v-show 控制的元素中時,必須額外在顯示條件為 true 時手動調用 scroll.refresh() 刷新 scroll 重新計算其高度。 3.當 scroll 在 v-if 控制的元素中時,則無須手動刷新,因為 scroll 組件會被重 新創建,scroll 內部的 mounted 鉤子的初始化及其對 data 的 watch 操作會自動 準確更新高度,實現滾動。 4.在 player.vue 中,由于全屏播放器和迷你播放器會被頻繁切換,而初始化代價也 并不是很大,所以使用 v-show 控制顯示,另外 watch player.isFullpage 的值來 手動刷新 scroll 即可。
// 全屏顯示的播放器... // 歌詞部分,可滾動 // lyricData是在組件mounted時后臺獲取的// 迷你顯示的播放器... ...// js 部分 watch 代碼 watch: { "player.isFullpage": function (newFlag) { if (newFlag) { this.$nextTick(() => { this.$refs.lyricScroll.refresh() }) }, ... }
-父組件與 scroll 組件之間 touch 系列事件同時觸發的問題
如在 player.vue 中,音樂播放器 CD 頁面和歌詞頁是左右滑動切換顯示的,封裝成 了 fade-slider 組件來控制頁面切換,在 fade-slider 中監聽 touch 系列事件來 控制左右滑動,而scroll 組件在歌詞頁面中使用,監聽 onscroll 事件控制歌詞滑動 上下切換,scroll 與 fade-slier 是父子關系,因此直接綁定事件時,冒泡過程中 二者的 touch 系列事件會同時被觸發。為了實現需求,即頁面左右滑動時 scroll 禁 止滾動,scroll 上下滾動時 fade-slider 也不要左右切換,必須做相應的處理。如 下代碼:
// player.vue 組件片段
// fade-slider 組件的 template 部分
1.要在歌詞頁面上下滑動歌詞時,即在 scroll 上下滾動時,使歌詞頁面 (fade-slider組件的中一個頁面)不要左右滑動,很簡單,在 fade-slider 的 touch 系列事件中對 touch 的位置和方向進行判斷即可。 2.反過來,要在 fade-slider 控制歌詞頁面左右滑動時,使歌詞頁面中的 scroll 不要上下滑動,因為它是封裝出來的 onscroll 事件,不能直接對 touch 的位置和方 向進行判斷,而另外去監聽它的 touch 系列事件雖然也可以處理問題,但顯然不合 適,不僅邏輯重復,而且組件與 DOM 的耦合性也過高,不合適。 3.因而,當前問題就是要在父組件的 touch 過程中,滿足一定條件時去阻止子組件 的 scroll 事件的觸發,顯然在冒泡過程中難以做到,因此解決方案: (1)fade-slider組件(父組件)中捕獲綁定 touch 系列事件:如 @touchstart.capture="onTouchStart" (2)在 touch 系列事件處理過程中,控制當確定是左右滑動行為時,阻止 touch 系 列事件的傳播:e.stopPropagation(),這樣,scroll 中的滾動就不會被觸發。 4.因此,總的邏輯就是: (1)touch 系列事件第一時間由父組件捕獲,進行 touch 行為的判斷 (2)如果是左右滑動,則切換頁面,同時阻止 touch 事件的進一步傳遞 (3)如果是上下滑動,則不做處理,使子組件的 touch 系列事件(scroll的內部)被觸發,進行處理。(2)自動滾動過程中 touch 相關問題 需求分析
如下圖:在歌詞頁面中,歌詞即使用 scroll 組件,在音樂播放過程中,歌詞會自動播放,即根據當前音樂所對應的歌詞,來 scrollToElement ,而在此過程中,仍然接受 touch 行為,當由 touch 引起滾動時,暫停歌詞的自動播放,并顯示歌詞控制條,同時根據滾動的距離高亮對應的歌詞。歌詞控制條分兩部分:左側顯示當前滾動到的歌詞對應的音樂的時間,右側顯示播放按鈕,點擊則直接播放此刻的音樂,歌詞也隨之重新定位
圖1:自動播放滾動時歌詞控制條不顯示,且高亮的歌詞是當前音樂的進度對應的歌詞
圖2:touch 引起滾動時,歌詞暫停播放(音樂播放狀依舊不變),歌詞控制條顯示,當前高亮歌詞由當前滾動到的位置決定
問題分析首先在滾動過程中高亮的歌詞以及歌詞控制條上顯示的對應的時間,顯然是要通過 onscroll 判斷,所以問題就在于如何在滾動過程中合理有效的區分是自動播放的滾動還是 touch 引起的滾動。
在確認是 touch 行為引起 scroll 滾動的前提下,大致要有三個階段,做不同的事情
(1)scrollStart階段:顯示歌詞控制條,停止歌詞的自動滾動 (2)onScroll階段:不斷根據當前滾動的偏移量更新高亮的歌詞,以及對應的時間 (3)scrollEnd階段:滾動結束后,設置一定時間(如 1s)后,隱藏歌詞控制條,恢復之前的播放狀態 (4)在以上階段的任何時刻,一旦歌詞控制條上的播放按鈕被點擊,都立即隱藏歌詞控制條,并更新播放狀態
總的來說,核心內容涉及到 touchStart、scrollStart、onScroll、scrollEnd四個事件,重點是這些事件的觸發順序,以及滾動慣性的問題
問題解決(一) 初步實現
(1)scroll 組件中已經綁定了并注冊了 ontouchStart,onscrollStart,onscroll,onscrollEnd事件(代碼見第一章), 在父組件中直接傳入相應值并監聽事件即可 (2)設置 touch標志,用來區分是否是自動滾動。在 touchStart 中 置其為 true,在 scrollEnd 置其為 false。之所以用 scrollEnd 作為結束時機而 不用 touchEnd 也是由于滾動慣性 (3)因此,自動滾動和 touch 滾動的處理流程分別如下圖:
(二) 慣性過程中 touch 引起的 bug 修復
初步實現中的流程基本已經可以實現需求,touch 的標志已經可以控制區分自動 滾動和touch 滾動,但是會發現如果在 scroll 的慣性滾動中,再次 touch 屏幕, 則慣性滾動會停止,但 scroll 系列事件會不再起作用,高亮的歌詞與此時 touch 的 位置也不對應,即在其系列事件中 touch 的標志被置為 false 了,而這顯然不是我 們想要的。 touch 的標志之所以被置為了 false,是由 scrollEnd 的觸發導致的。在慣性 滾動過程中,touch 屏幕則會阻止慣性滾動,這是很明顯的現象,據此想一想,肯定是 touch 導致了 scrollEnd 的提前觸發。即如下圖:
因此,除了 touch 標志之外,還需一個 end 標志來確定 scroll 系列流程是否被 touch 行為提前打斷。 1. 在 touchStart 中置 end 標志為 true 2. 在 scrollStart 中置 end 標志為 false 3. 在 scrollEnd 中置 end 標志為 true 4. 在 scrollEnd 中增加判斷,如果 end 標志為 true,則不置 touch 標志為 false
(三) touchStart、scrollStart、onscroll、scrollEnd 在 scroll 組件中注冊的區別
scrollStart、onscroll、scrollEnd 均是 better-scroll 中注冊的事件,使用時在 better-scroll 對象(new BetterScroll())上 .on(事件名,處理函數) 監聽即可
touchStart 是原生事件,在 scroll 組件中綁定在最外層元素上
三、完整項目地址Github: https://github.com/aphasic/mu...
文章版權歸作者所有,未經允許請勿轉載,若此文章存在違規行為,您可以聯系管理員刪除。
轉載請注明本文地址:http://specialneedsforspecialkids.com/yun/112735.html
一、 基礎實現 (1)功能 對 better-scroll 插件的基本封裝,實現移動端的滾動 (2)實現 引入 better-scroll props probeType: better-scroll 配置項之一 (1)取值: 1 滾動的時候會派發 scroll 事件,會截流。 2 滾動的時候實時派發 scroll 事件,不會截流。 3 除了實時派發 scroll 事件,在 swipe 的情況...
一、 基礎實現 (1)功能 對 better-scroll 插件的基本封裝,實現移動端的滾動 (2)實現 引入 better-scroll props probeType: better-scroll 配置項之一 (1)取值: 1 滾動的時候會派發 scroll 事件,會截流。 2 滾動的時候實時派發 scroll 事件,不會截流。 3 除了實時派發 scroll 事件,在 swipe 的情況...
摘要:在中新建組件許文瑞正在吃屎。。。。在中添加如下代碼三歌手組件開發歌手首頁開發數據獲取數據獲取依舊從音樂官網獲取歌手接口創建我們和以前一樣,利用我們封裝的等發放,來請求我們的接口,返回給。 Vue-Music 跟學一個網課老師做的仿原生音樂APP跟學的筆記,記錄點滴,也希望對學習vue初學小伙伴有點幫助 showImg(https://segmentfault.com/img/remot...
摘要:概述項目是基于,成品是一個移動端的音樂播放器,來源于的實戰課程。播放器是全局組件,放在下面,通過傳遞數據,觸發提交,從而使播放器開始工作。將請求的數據格式化后再通過傳遞,組件間共享,實現歌曲的播放切換等。 概述 項目是基于Vue.js,成品是一個移動端的音樂播放器,來源于imooc的實戰課程。自己動手實踐并加以修改拓展。項目的大致流程是Vue-cli構建開發環境,分析需求,設計構思,規...
閱讀 1026·2021-11-22 13:53
閱讀 1577·2021-11-17 09:33
閱讀 2372·2021-10-14 09:43
閱讀 2835·2021-09-01 11:41
閱讀 2262·2021-09-01 10:44
閱讀 2904·2021-08-31 09:39
閱讀 1443·2019-08-30 15:44
閱讀 1853·2019-08-30 13:02