懶癌發(fā)作……
本篇有關(guān)于列表滾動(dòng)的內(nèi)容听系,有點(diǎn)復(fù)雜涝滴,好好分析
0. 其它
vue實(shí)戰(zhàn)(1):準(zhǔn)備與資料整理
vue實(shí)戰(zhàn)(2):初始化項(xiàng)目吧黄、搭建底部導(dǎo)航路由
vue實(shí)戰(zhàn)(3):底部導(dǎo)航顯示肺魁、搭建各模塊靜態(tài)頁(yè)面添瓷、添加登錄頁(yè)頁(yè)面與路由
vue實(shí)戰(zhàn)(4):postman測(cè)試數(shù)據(jù)渺蒿、封裝ajax痢士、使用vuex管理狀態(tài)
vue實(shí)戰(zhàn)(5):總結(jié)一
vue實(shí)戰(zhàn)(6):異步顯示數(shù)據(jù)、開(kāi)發(fā)Star組件
vue實(shí)戰(zhàn)(7):完整開(kāi)發(fā)登錄頁(yè)面(一)
vue實(shí)戰(zhàn)(8):完整開(kāi)發(fā)登錄頁(yè)面(二)
vue實(shí)戰(zhàn)(9):總結(jié)二
vue實(shí)戰(zhàn)(10):開(kāi)發(fā)店鋪詳情(一)
vue實(shí)戰(zhàn)(11):開(kāi)發(fā)店鋪詳情(二)
vue實(shí)戰(zhàn)(12):完結(jié) + 附學(xué)習(xí)視頻
1. 分析與引入相關(guān)庫(kù)
-
靜態(tài)頁(yè)面效果
靜態(tài)頁(yè)面.png - 需要實(shí)現(xiàn)的效果
ID | 效果 |
---|---|
1 | 左右兩邊列表可以滑動(dòng)茂装,有回彈效果 |
2 | 當(dāng)滑動(dòng)右側(cè)列表時(shí)怠蹂,更新當(dāng)前分類(lèi)(即對(duì)應(yīng)左側(cè)列表類(lèi)型) |
3 | 點(diǎn)擊左側(cè)某個(gè)分類(lèi)時(shí),右側(cè)列表滑動(dòng)到對(duì)應(yīng)類(lèi)型位置 |
類(lèi)名:
current
標(biāo)識(shí)當(dāng)前分類(lèi)(用于顏色變換等)計(jì)算屬性:
currentIndex
————scrollY
: 右側(cè)滑動(dòng)的Y軸坐標(biāo)
————tops
: 所有右側(cè)分類(lèi)li
的top
組成的數(shù)組代碼實(shí)現(xiàn)
ID | 需實(shí)現(xiàn)內(nèi)容 |
---|---|
1 | 在滑動(dòng)過(guò)程中少态,實(shí)時(shí)收集 scrollY
|
2 | 列表第一次加載顯示后城侧,收集 tops
|
3 | 實(shí)現(xiàn)currentIndex 計(jì)算邏輯 |
- 關(guān)于滑動(dòng)
ID | 滑動(dòng)情況(移動(dòng)端) |
---|---|
1 | 手指一直滑動(dòng),手指不脫離屏幕 |
2 | 慣性滑動(dòng)彼妻,手指滑動(dòng)后列表慣性滑動(dòng) |
3 | 編碼滑動(dòng)嫌佑,如點(diǎn)擊事件,點(diǎn)擊類(lèi)型滑動(dòng)到相關(guān)位置 |
BetterScroll
這邊的滑動(dòng)就借助 BetterScroll 侨歉,挺好用的
鏈接:betterscroll官網(wǎng)
鏈接:better-scroll 作者文章《當(dāng) better-scroll 遇見(jiàn) Vue》
鏈接:better-scroll 社區(qū)地址安裝 BetterScroll
根據(jù)官網(wǎng)屋摇,進(jìn)行安裝與引用
npm install better-scroll --save
在需要的頁(yè)面引用:import BScroll from 'better-scroll'
2. 獲取并計(jì)算相關(guān)數(shù)據(jù)
- 引入組件
引用 BetterScroll 滑動(dòng)組件與前面引用 Swiper 輪播組件的方式如出一轍,需要進(jìn)行數(shù)據(jù)監(jiān)測(cè)幽邓,獲取的數(shù)據(jù)加載完成后再加載組件
methods: {
...mapActions('msite', ['getShopGoods']),
// 使用組件
_scrollY () {
// 左側(cè)類(lèi)型列表
new BScroll('.menu-wrapper', {
})
// 右側(cè)食物列表
new BScroll('.foods-wrapper', {
})
}
},
computed: {
...mapState('msite', ['goods']),
// 計(jì)算
currentIndex () {
}
},
watch: { // 監(jiān)測(cè)
goods (value) {
this.$nextTick(() => { // 數(shù)據(jù)加載完后執(zhí)行
this._scrollY()
})
}
}
- 定義收集右側(cè)列表滑動(dòng)的Y軸坐標(biāo)
scrollY
的方法
—— 看官網(wǎng)文檔炮温,需要使用on
方法去進(jìn)行綁定事件
on方法
—— 為on
方法綁定scroll
事件
自定義事件 -
滑動(dòng)的方式
有三種方式,可以都試一下牵舵,看看效果茅特,然后選擇適用的
probeType - 分析選擇
根據(jù)打印效果選擇,選擇第二種方式最合適
methods: {
...mapActions('msite', ['getShopGoods']),
// 使用組件
_scrollY () {
// 左側(cè)類(lèi)型列表
new BScroll('.menu-wrapper', {
})
// 右側(cè)食物列表
const foodscroll = new BScroll('.foods-wrapper', {
probeType: 2 // 慣性滑動(dòng)不會(huì)觸發(fā)
})
// 操作食物列表
foodscroll.on('scroll', ({ x, y }) => {
console.log('橫坐標(biāo):' + x, '縱坐標(biāo):' + y)
this.scrollY = Math.abs(y) // y軸的值轉(zhuǎn)換為絕對(duì)值
})
}
},
computed: {
...mapState('msite', ['goods']),
// 計(jì)算
currentIndex () {
}
},
watch: { // 監(jiān)測(cè)
goods (value) {
this.$nextTick(() => { // 數(shù)據(jù)加載完后執(zhí)行
this._scrollY()
})
}
}
方式1 | 效果1 | 效果2 |
---|---|---|
probeType: 1 |
在滑動(dòng)時(shí)有輸出祖很,但數(shù)據(jù)不是實(shí)時(shí)輸出 | 慣性滑動(dòng)時(shí)不輸出 |
方式2 | 效果1 | 效果2 |
---|---|---|
probeType: 2 |
在緩慢滑動(dòng)時(shí)有輸出笨鸡,數(shù)據(jù)實(shí)時(shí)輸出 | 慣性滑動(dòng)時(shí)不輸出 |
方式3 | 效果1 | 效果2 |
---|---|---|
probeType: 3 |
輕微滑動(dòng),數(shù)據(jù)輸出迅速,數(shù)據(jù)實(shí)時(shí)輸出 | 慣性滑動(dòng)時(shí)同樣輸出 |
3. 收集 tops
收集右側(cè)列表滑動(dòng)的Y軸坐標(biāo),選擇第二種滑動(dòng)方式
- 初始化時(shí)收集
tops
// 收集tops
_initTops () {
// 初始化,定義最上頭的位置為0
const toplis = []
let top = 0
toplis.push(top)
// 收集
// $refs 用于操作dom , foodsUl 為 ref='foodsUl' 設(shè)置在 ul 節(jié)點(diǎn)上累澡,children 為取其下的 li
const lis = this.$refs.foodsUl.children
Array.prototype.slice.call(lis).forEach(li => {
top += li.clientHeight
toplis.push(top)
})
// 更新數(shù)據(jù)
this.tops = toplis
console.log(toplis)
}
4. 計(jì)算當(dāng)前分類(lèi)的下標(biāo)
// 計(jì)算當(dāng)前分類(lèi)的下標(biāo)
currentIndex () {
// 條件
const { scrollY, tops } = this
// 計(jì)算,取區(qū)間返回上一個(gè)值
const index = tops.findIndex((top, index) => {
console.log(top, index)
// 返回結(jié)果: scrollY >= 當(dāng)前top && scrollY < 下一個(gè)top
return scrollY >= top && scrollY < tops[index + 1]
})
return index
}
-
鏈接:Array.prototype.findIndex()
滑動(dòng)更新左側(cè)分類(lèi).gif -
解決慣性滑動(dòng)的 bug
慣性滑動(dòng)的時(shí)候左側(cè)分類(lèi)不隨著更新
解決辦法:查看 BetterScroll 官網(wǎng),添加滑動(dòng)結(jié)束的監(jiān)聽(tīng)
監(jiān)聽(tīng)滑動(dòng)結(jié)束.png
// 監(jiān)聽(tīng)滑動(dòng)結(jié)束
foodscroll.on('scrollEnd', ({ x, y }) => {
// console.log('橫坐標(biāo):' + x, '縱坐標(biāo):' + y)
this.scrollY = Math.abs(y) // 轉(zhuǎn)換為絕對(duì)值
})
5. 點(diǎn)擊左側(cè)分類(lèi)滑動(dòng)
添加點(diǎn)擊事件
<li class="menu-item " v-for="(good, index) in goods" :key="index" :class="{current:index === currentIndex}" @click="clickMenuItem(index)">
-
查看 BetterScroll 官網(wǎng)旅东,找到相關(guān)方法
scrollTo
scrollTo方法.png 方法
// 左側(cè)分類(lèi)列表點(diǎn)擊事件
clickMenuItem (index) {
console.log(index)
// 得到目標(biāo)位置的scrollY
const scrollY = this.tops[ index ]
// 立即更新scrollY(讓點(diǎn)擊的分類(lèi)項(xiàng)成為當(dāng)前分類(lèi))
this.scrollY = scrollY
// 平滑滑動(dòng)右側(cè)列表
this.foodscroll.scrollTo(0, -scrollY, 400)
}
6. 結(jié)束
這個(gè)滑動(dòng)的功能看起來(lái)不難,但是分析起來(lái)感覺(jué)還是有些道道的;
前段時(shí)間有點(diǎn)生病拷姿,電腦又壞了陡舅,最坑爹的是剛過(guò)保修期維修花了500,真是花錢(qián)容易賺錢(qián)難,加之最近很浮躁,導(dǎo)致根本無(wú)心學(xué)習(xí);
拖到現(xiàn)在,這個(gè)星期這個(gè)項(xiàng)目必結(jié)束聚至。