滾動位置固定:在vue中經過路由切換頁面時組件會自動滾動到頂部,須要監聽滾動行爲才能讓滾動位置固定,better-scroll解決了這個問題。html
經常使用效果:移動端很常見的效果,當滑動右邊部分的時候,左邊會聯動顯示與當前內容相符合的標題高亮,當點擊左邊某一個標題的時候,右邊會自動滑動到相應的內容。vue
npm install better-scroll --savegit
import BScroll from 'better-scroll'github
注意使用better-scroll的基本條件npm
//建立一個新實例 而且 對class爲wrapper對象 實現了一個縱向可點擊的滾動效果 let scroll = new BScroll('.wrapper',{ scrollY: true, click: true })
實現及說明數組
1.滾動效果app
better-scroll在使用的時候須要在dom元素渲染完成以後初始化better-scroll的實例,初始化的時候,先要獲取須要滑動的元素,而後在初始化的時候將獲取到的元素傳遞給初始化函數,此時即可實現滑動效果dom
2.左右聯動效果函數
左右聯動效果的實現,是better-scroll經過監聽事件實現的。動畫
首先獲取到右邊內容盒子的高度,而後獲取到該盒子中每一項的高度並作前n項高度累加(第n項的高度是前n項的高度和)存儲到listHeight數組中。在初始化的時候傳遞屬性probeType=3 (探針的效果,時時獲取滾動高度),並給右邊的內容盒子對象監聽scroll事件,從而時時獲取Y軸位置,來與listHeight數組中的數據作比較,時時計算當前的索引值,並給對邊對應索引值的項添加背景色高亮,從而實現右邊滑動,聯動左邊。
當點擊左邊的每一項的時候,獲取到當前的索引值,並根據當前的索引值獲取到與右邊內容盒子中對應索引的元素,右邊的盒子元素經過監聽scrollToElement,並傳遞獲取到的對應索引元素和動畫時間,從而實現點擊左邊,實現右邊聯動;
<template> <div ref="wrapper"> <slot></slot> </div> </template> <script> import BScroll from 'better-scroll'; export default { props: { /** * 1 滾動的時候會派發scroll事件,會截流。 * 2 滾動的時候實時派發scroll事件,不會截流。 * 3 除了實時派發scroll事件,在swipe的狀況下仍然能實時派發scroll事件 */ probeType: { type: Number, default: 1 }, /** * 點擊列表是否派發click事件 */ click: { type: Boolean, default: true }, /** * 是否開啓橫向滾動 */ scrollX: { type: Boolean, default: false }, /** * 是否派發滾動事件 */ listenScroll: { type: Boolean, default: false }, /** * 列表的數據 */ data: { type: Object, default: [] }, /** * 是否派發滾動到底部的事件,用於上拉加載 */ pullup: { type: Boolean, default: false }, /** * 是否派發頂部下拉的事件,用於下拉刷新 */ pulldown: { type: Boolean, default: false }, /** * 是否派發列表滾動開始的事件 */ beforeScroll: { type: Boolean, default: false }, /** * 當數據更新後,刷新scroll的延時。 */ refreshDelay: { type: Number, default: 20 } }, mounted() { // 保證在DOM渲染完畢後初始化better-scroll console.log(this.data); setTimeout(() => { this._initScroll() }, 20) }, methods: { _initScroll() { if (!this.$refs.wrapper) { return } this.$nextTick(() => { if(!this.scroll){ // better-scroll的初始化 this.scroll = new BScroll(this.$refs.wrapper, { probeType: this.probeType, click: this.click, scrollX: this.scrollX }) }else{ this.scroll.refresh(); } }) // 是否派發滾動事件 if (this.listenScroll) { let me = this this.scroll.on('scroll', (pos) => { me.$emit('scroll', pos) console.log(pos); }) } // 是否派發滾動到底部事件,用於上拉加載 if (this.pullup) { this.scroll.on('scrollEnd', () => { // 滾動到底部 if (this.scroll.y <= (this.scroll.maxScrollY + 50)) { this.$emit('pullup') } }) } // 是否派發頂部下拉事件,用於下拉刷新 if (this.pulldown) { this.scroll.on('touchend', (pos) => { // 下拉動做 if (pos.y > 50) { this.$emit('pulldown') } }) } // 是否派發列表滾動開始的事件 if (this.beforeScroll) { this.scroll.on('beforeScrollStart', () => { this.$emit('beforeScroll') }) } }, disable() { // 代理better-scroll的disable方法 this.scroll && this.scroll.disable() }, enable() { // 代理better-scroll的enable方法 this.scroll &&this.scroll.enable() }, refresh(){ // 代理better-scroll的refresh方法 this.scroll &&this.scroll.refresh() }, scrollTo(){ // 代理better-scroll的scrollTo方法 this.scroll &&this.scroll.scrollTo.apply(this.scroll, arguments) }, scrollToElement(){ // 代理better-scroll的scrollToElement方法 this.scroll &&this.scroll.scrollToElement.apply(this.scroll, arguments) }, }, watch:{ // 監聽數據的變化,延時refreshDelay時間後調用refresh方法從新計算,保證滾動效果正常 data(data){ console.log(data) setTimeout(()=>{this.refresh()},this.refreshDelay) } } } </script>