vue封裝實現(xiàn)自動循環(huán)滾動的列表
前言
在做數(shù)據(jù)大屏開發(fā)的過程中,經(jīng)常出現(xiàn)需要對列表進(jìn)行自動滾動的需求,為了個性化的實現(xiàn)各種需求,就封裝了一個函數(shù)方法
解決方案
- 生成一個父元素,并給其固定的高度,通過$refs獲取并賦值給
container
變量 - 獲取一些關(guān)于
container
和其子元素的信息,如父容器高度(parentHeight
)、滾動高度(scrollHeight
)、第一個子元素的高度(childHeight
)、子元素數(shù)量(childCount
)、最大高度(maxHeight
)、當(dāng)前滾動位置(toHeight
)和當(dāng)前子元素索引(current
),并初始化一個名為timer
的計時器。 - 定義一個名為
scrollCore
的函數(shù),該函數(shù)用于實現(xiàn)滾動效果。 - 在
scrollCore
函數(shù)中檢查如果scrollHeight
大于parentHeight
,則創(chuàng)建一個定時器,以便每隔一段時間執(zhí)行一次滾動操作。 - 在定時器中,
scrollCore
函數(shù)中逐漸增加容器的scrollTop
屬性,從而實現(xiàn)滾動效果。
一、勻速自動滾動,并實現(xiàn)方法可對多個列表復(fù)用
思路:通過對ref的命名,來實現(xiàn)在方法中使用for循環(huán)來對多個列表生效
<template> <div> <ul class="shiJianGaoJingContent_right" ref="scroll0"> <li class="gaojing_info_list" v-for="(item, index) in scrollInfoList" :key="index"> </li> </ul> </div> </template> <script> export default { data() { return { scrollInfoList:[], }; }, methods: { // 列表自動滾動 scrollFn() { let dataList = []; for (let i = 0; i < 1; i++) { let container = this.$refs["scroll" + i]; let parentHeight = container.offsetHeight || 0; let scrollHeight = container.scrollHeight; let childHeight = container.firstChild.offsetHeight; let childCount = container.childNodes.length; let maxHeight = childHeight * childCount; let toHeight = container.scrollTop; let current = 0; dataList.push({ parentHeight, scrollHeight, childHeight, childCount, maxHeight, toHeight, current, timer: null, timerMouseWheel: null, }); function scrollCore() { { if (scrollHeight > parentHeight) { dataList[i].timer = setInterval(() => { let scrollStep = 1; // 每幀滾動的步長,可以適當(dāng)調(diào)整 if (container.scrollTop + parentHeight + 5 >= scrollHeight) { // 如果滾動到底部,則將滾動位置重置為0 container.scrollTop = 0; dataList[i].toHeight = 0; dataList[i].current = 0; } else { if (container.scrollTop < dataList[i].toHeight + dataList[i].childHeight) { // 如果尚未滾動到目標(biāo)位置,則逐幀更新滾動位置 container.scrollTop += scrollStep; } else { // 已滾動到目標(biāo)位置,更新當(dāng)前子項索引和子項高度 dataList[i].current = (dataList[i].current + 1) % dataList[i].childCount; dataList[i].childHeight = container.childNodes[dataList[i].current].offsetHeight; dataList[i].toHeight = container.scrollTop; } } }, 2000 / 60); // 設(shè)置每秒更新60次,可根據(jù)需求調(diào)整 } } } scrollCore() } }, }, mounted() {}, }; </script>
注:該方法在自動滾動到底部后會返回到頂部,循環(huán)滾動需要更改邏輯,在下方有循環(huán)的方法。
二、如何暫時關(guān)閉自動滾動
當(dāng)我們想自己通過鼠標(biāo)滾輪滾動該列表時,使該列表的自動滾動暫停,我們可以添加了一個名為mousewheel
的事件監(jiān)聽器,以便在鼠標(biāo)滾輪滾動時執(zhí)行以下操作:
- 清除之前的定時器
dataList[i].timer
和dataList[i].timerMouseWheel
。 - 更新
dataList[i].toHeight
為當(dāng)前滾動位置,并將滾動位置設(shè)置為相同的值。 - 設(shè)置一個新的定時器
dataList[i].timerMouseWheel
,在一段時間后重新調(diào)用scrollCore
函數(shù),以恢復(fù)自動滾動效果。
container.addEventListener("mousewheel", () => { this.$nextTick(() => { clearInterval(dataList[i].timer); clearInterval(dataList[i].timerMouseWheel); dataList[i].toHeight = container.scrollTop; container.scrollTop = container.scrollTop; dataList[i].timerMouseWheel = setTimeout(() => { scrollCore() }, 3000) }); });
三、如何徹底關(guān)閉自動滾動
在上面的方法中會一直無限的滾動下去,那么我們?nèi)绻胪O戮唧w看某一項要把自動滾動關(guān)閉掉呢,我們可以通過將關(guān)閉方法寫在container
的某個事件中,并將該事件派發(fā)給container
來實現(xiàn)
// 監(jiān)聽關(guān)閉自動滾動的事件 container.addEventListener("closeScroll", () => { this.$nextTick(() => { clearInterval(dataList[i].timer); clearInterval(dataList[i].timerMouseWheel); toHeight = container.scrollTop; container.scrollTop = container.scrollTop; }); });
// 完整代碼 // 關(guān)閉列表自動滾動 closeListScroll(container) { // 創(chuàng)建一個新的 自定義 事件 const closeScroll = new Event("closeScroll"); container.dispatchEvent(closeScroll) }, // 列表自動滾動 scrollFn() { let dataList = []; for (let i = 0; i < 1; i++) { let container = this.$refs["scroll" + i]; let parentHeight = container.offsetHeight || 0; let scrollHeight = container.scrollHeight; let childHeight = container.firstChild.offsetHeight; let childCount = container.childNodes.length; let maxHeight = childHeight * childCount; let toHeight = container.scrollTop; let current = 0; dataList.push({ parentHeight, scrollHeight, childHeight, childCount, maxHeight, toHeight, current, timer: null, timerMouseWheel: null, }); function scrollCore() { { if (scrollHeight > parentHeight) { dataList[i].timer = setInterval(() => { let scrollStep = 1; // 每幀滾動的步長,可以適當(dāng)調(diào)整 if (container.scrollTop + parentHeight + 5 >= scrollHeight) { // 如果滾動到底部,則將滾動位置重置為0 container.scrollTop = 0; dataList[i].toHeight = 0; dataList[i].current = 0; } else { if (container.scrollTop < dataList[i].toHeight + dataList[i].childHeight) { // 如果尚未滾動到目標(biāo)位置,則逐幀更新滾動位置 container.scrollTop += scrollStep; } else { // 已滾動到目標(biāo)位置,更新當(dāng)前子項索引和子項高度 dataList[i].current = (dataList[i].current + 1) % dataList[i].childCount; dataList[i].childHeight = container.childNodes[dataList[i].current].offsetHeight; dataList[i].toHeight = container.scrollTop; } } }, 2000 / 60); // 設(shè)置每秒更新60次,可根據(jù)需求調(diào)整 } } } scrollCore() container.addEventListener("mousewheel", () => { this.$nextTick(() => { clearInterval(dataList[i].timer); clearInterval(dataList[i].timerMouseWheel); dataList[i].toHeight = container.scrollTop; container.scrollTop = container.scrollTop; dataList[i].timerMouseWheel = setTimeout(() => { scrollCore() }, 3000) }); }); container.addEventListener("closeScroll", () => { this.$nextTick(() => { clearInterval(dataList[i].timer); clearInterval(dataList[i].timerMouseWheel); toHeight = container.scrollTop; container.scrollTop = container.scrollTop; }); }); } },
通過如上代碼 我們就可以通過調(diào)用closeListScroll()
方法來關(guān)閉列表自動滾動,如我們想要關(guān)閉ref=scroll0列表的自動滾動
// 示例 關(guān)閉ref=scroll0列表的自動滾動 // 某個方法中 clickSomeBtn(){ ... //其他邏輯 this.closeListScroll(this.$refs["scroll0"]) }
四、如何使自動滾動無限循環(huán),使其頭尾相連
思路:將一份數(shù)據(jù)復(fù)制為兩份,在滾動到第二份與第一份重合的時候 立刻將滾動高度歸位,這樣從視覺效果上來看,就是無限滾動的效果 要實現(xiàn)這個效果,首先是我們需要將一份數(shù)據(jù)變?yōu)閮煞?,最為簡單的實現(xiàn)思路為直接將數(shù)據(jù)變?yōu)閮煞?/p>
<li class="gaojing_info_list" v-for="(item, index) in [...scrollInfoList,...scrollInfoList]" :key="index">
但是這樣的話,我們需要對所有的列表都進(jìn)行更改,容易遺漏,不符合封裝思路
于是我就想著通過DOM方法直接在封裝函數(shù)中進(jìn)行操作,實現(xiàn)思路為
- 使用DOM方法獲取
container
的所有子元素,并將它們存儲在名為children
的變量中。 - 創(chuàng)建一個文檔片段(Document Fragment)并將子元素逐個克隆并添加到文檔片段中。
- 一次性將文檔片段添加回
container
中,以提高性能。 當(dāng)我們實現(xiàn)了克隆兩份數(shù)據(jù)后,通過對container.scrollTop >= scrollHeight / 2
的判斷,來得到我們已經(jīng)來到了第二頁與初始位置重復(fù)的位置,在這個時候?qū)L動位置重置,在視覺上就會實現(xiàn)首尾相連無限滾動的效果
// 列表自動循環(huán)滾動 scrollFn() { let dataList = []; for (let i = 0; i < 1; i++) { let container = this.$refs["scroll" + i]; console.log(container); // 使用 DOM 方法獲取所有子元素 let children = container.children; // 創(chuàng)建一個文檔片段 let fragment = document.createDocumentFragment(); // 將子元素逐個重新插入到容器中 for (let ind = 0; ind < children.length; ind++) { const child = children[ind].cloneNode(true); console.log(child, "child"); fragment.appendChild(child); } // 一次性將文檔片段添加回容器中 this.$refs["scroll" + i].appendChild(fragment); let parentHeight = container.offsetHeight || 0; let scrollHeight = container.scrollHeight; let childHeight = container.firstChild.offsetHeight; let childCount = container.childNodes.length; let maxHeight = childHeight * childCount; let toHeight = container.scrollTop; let current = 0; dataList.push({ parentHeight, scrollHeight, childHeight, childCount, maxHeight, toHeight, current, timer: null, }); function scrollCore() { if (scrollHeight > parentHeight) { dataList[i].timer = setInterval(() => { let scrollStep = 1; // 每幀滾動的步長,可以適當(dāng)調(diào)整 if (container.scrollTop >= scrollHeight / 2) { // 滾動到與第一行重復(fù)的位置后 重置 container.scrollTop = 0; dataList[i].toHeight = 0; dataList[i].current = 0; } else { if ( container.scrollTop < dataList[i].toHeight + dataList[i].childHeight ) { // 如果尚未滾動到目標(biāo)位置,則逐幀更新滾動位置 container.scrollTop += scrollStep; } else { // 已滾動到目標(biāo)位置,更新當(dāng)前子項索引和子項高度 dataList[i].current = (dataList[i].current + 1) % dataList[i].childCount; dataList[i].childHeight = container.childNodes[dataList[i].current].offsetHeight; dataList[i].toHeight = container.scrollTop; } } }, 2000 / 60); // 設(shè)置每秒更新60次,可根據(jù)需求調(diào)整 } } scrollCore(); container.addEventListener("mousewheel", () => { this.$nextTick(() => { clearInterval(dataList[i].timer); clearInterval(dataList[i].timerMouseWheel); dataList[i].toHeight = container.scrollTop; container.scrollTop = container.scrollTop; dataList[i].timerMouseWheel = setTimeout(() => { scrollCore(); }, 3000); }); }); container.addEventListener("closeScroll", () => { this.$nextTick(() => { clearInterval(dataList[i].timer); clearInterval(dataList[i].timerMouseWheel); toHeight = container.scrollTop; container.scrollTop = container.scrollTop; }); }); } }
以上就是vue封裝實現(xiàn)自動循環(huán)滾動的列表的詳細(xì)內(nèi)容,更多關(guān)于vue循環(huán)滾動列表的資料請關(guān)注腳本之家其它相關(guān)文章!
相關(guān)文章
Vue?結(jié)合Sortablejs實現(xiàn)table行排序功能
在一個列表展示頁面上,使用了表格組件,原有組件本身不支持拖拽功能,需求要求在列表的基礎(chǔ)上支持行拖拽排序,因此引入了www.sortablejs.com插件,接下來通過本文給大家講解Vue?結(jié)合Sortablejs實現(xiàn)table行排序功能,需要的朋友可以參考下2022-10-10在Vue中使用CSS3實現(xiàn)內(nèi)容無縫滾動的示例代碼
這篇文章主要介紹了在Vue中使用CSS3實現(xiàn)內(nèi)容無縫滾動的示例代碼,文中通過示例代碼介紹的非常詳細(xì),對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧2020-11-11Vue組件通信中非父子組件傳值知識點(diǎn)總結(jié)
在本篇文章里小編給大家整理的是關(guān)于Vue組件通信中非父子組件傳值知識點(diǎn)總結(jié),有興趣的朋友們學(xué)習(xí)下。2019-12-12vue?parseHTML源碼解析hars?end?comment鉤子函數(shù)
這篇文章主要為大家介紹了vue?parseHTML源碼解析hars?end?comment鉤子函數(shù)示例詳解,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪2022-07-07