基于better-scroll的picker組件實(shí)現(xiàn)

這里再安利一下better-scroll這個(gè)組件庫,該庫的源代碼結(jié)構(gòu)清晰,借鑒了vue源碼的組織形式。better-scroll提供的各功能模塊相互獨(dú)立,易于閱讀,對(duì)初學(xué)者非常友好,建議學(xué)習(xí)一下。
另外,我們可以借助better-scroll提供的功能封裝出更為復(fù)雜的組件。這里要說的picker選擇器組件就是基于better-scroll提供的特性實(shí)現(xiàn)的。


實(shí)現(xiàn)原理

這里主要借助better-scroll提供的wheel屬性,利用該屬性并配合相應(yīng)的html結(jié)構(gòu)以及css樣式可以很簡單的實(shí)現(xiàn)選擇器組件。

<template>
    <div class="wheel-wrapper" ref="wrapper">
        <ul class="wheel-scroller">
            <li class="wheel-item" v-for="index in data">{{index}}</li>
        </ul>
    </div>
</template>
<script>
    const EVENT_CHANGE = 'change'
    import BScroll from 'better-scroll'
    export default {
        props: {
            data: {
                type:Array,
                default:function(){
                    return []
                }
            },
            selectedIndex: {
                type:Number,
                default:0
            }
        },
        data() {
            return {
                
            }    
        },
        mounted() {
            this.$nextTick(() => {
                this._createWheel().enable()
            })
        },
        methods: {
         _createWheel() {
            if (!this.wheels) {
              const wheel = this.wheels = new BScroll(this.$refs.wrapper, {
                wheel: {
                  selectedIndex: this.selectedIndex,
                  wheelWrapperClass: 'wheel-scroller',
                  wheelItemClass: 'wheel-item',
                  rotate: 0
                },                
                observeDOM: false
              })  
              wheel.on('scrollEnd', () => {
                //滾動(dòng)完成之后獲取當(dāng)前選取的索引值
                this.$emit(EVENT_CHANGE,wheel.getSelectedIndex())
              })            
            } else {
              this.wheels.refresh()
            }
            return this.wheels
          },
        }
    }
</script>
<style lang="scss" scoped>
    .wheel-wrapper{
        height: 100px;               
        overflow: hidden;
        .wheel-scroller{
            .wheel-item{
                line-height:24px;
            }
        }
    }
</style>

以上代碼實(shí)現(xiàn)的效果圖如下所示,第一行即為當(dāng)前選中的選項(xiàng),我們接下來要做的事情就是給選中的選項(xiàng)設(shè)計(jì)樣式。


image

樣式設(shè)計(jì)

<template>
    <div class="relative">
        <div class="mask-top absolute"></div>
        <div class="mask-bottom absolute"></div>
        <div class="wheel-wrapper" ref="wrapper">
            <ul class="wheel-scroller">
                <li class="wheel-item" v-for="index in data">{{index}}</li>
            </ul>
        </div>
    </div>    
</template>
<script>
    const EVENT_CHANGE = 'change'
    import BScroll from 'better-scroll'
    export default {
        props: {
            data: {
                type:Array,
                default:function(){
                    return []
                }
            },
            selectedIndex: {
                type:Number,
                default:0
            }
        },
        data() {
            return {
                
            }    
        },
        mounted() {
            this.$nextTick(() => {
                this._createWheel().enable()
            })
        },
        methods: {
         _createWheel() {
            if (!this.wheels) {
              const wheel = this.wheels = new BScroll(this.$refs.wrapper, {
                wheel: {
                  selectedIndex: this.selectedIndex,
                  wheelWrapperClass: 'wheel-scroller',
                  wheelItemClass: 'wheel-item',
                  rotate: 0
                },                
                observeDOM: false
              })  
              wheel.on('scrollEnd', () => {
                //滾動(dòng)完成之后獲取當(dāng)前選取的索引值
                this.$emit(EVENT_CHANGE,wheel.getSelectedIndex())
              })            
            } else {
              this.wheels.refresh()
            }
            return this.wheels
          },
        }
    }
</script>
<style lang="scss" scoped>
    .relative{
        position: relative;
    }
    .absolute{
        position: absolute;        
    }
    .mask-top{
        height:24px;
        width:100%;
        top:0;
        border-bottom:1px solid red;
    }
    .mask-bottom{
        height:24px;
        width:100%;
        top:24px;
        border-bottom:1px solid red;
        background:red;
        z-index:-1;
    }
    .wheel-wrapper{
        height: 100px;                    
        overflow: hidden;
        .wheel-scroller{
            margin-top:24px; 
            .wheel-item{
                line-height:24px;
            }
        }
    }
</style>

以上代碼實(shí)現(xiàn)的效果如下圖所示,這里只給出了簡單的原理以及演示,具體實(shí)現(xiàn)可根據(jù)自己的實(shí)際情況設(shè)計(jì)。


image

擴(kuò)展

這里只演示了單列選擇器組件,相對(duì)來說簡單,我們?cè)陂_發(fā)時(shí)常遇到的情形是多列的情況,再復(fù)雜就是各列存在聯(lián)動(dòng)關(guān)系。至于多列的設(shè)計(jì),這里只需要?jiǎng)?chuàng)建多個(gè)better-scroll的實(shí)例即可。若存在多列聯(lián)動(dòng)的情形,需要根據(jù)滾動(dòng)情況動(dòng)態(tài)的輸入相應(yīng)了list,這里不再對(duì)詳細(xì)設(shè)計(jì)做贅述。

總結(jié)

基于better-scroll還可以設(shè)計(jì)出很多復(fù)雜實(shí)用的組件,在后續(xù)會(huì)不斷總結(jié)。。。。。

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時(shí)請(qǐng)結(jié)合常識(shí)與多方信息審慎甄別。
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡書系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

  • 1、通過CocoaPods安裝項(xiàng)目名稱項(xiàng)目信息 AFNetworking網(wǎng)絡(luò)請(qǐng)求組件 FMDB本地?cái)?shù)據(jù)庫組件 SD...
    陽明AI閱讀 16,171評(píng)論 3 119
  • 今天早上,我
    金鋮天清閱讀 180評(píng)論 0 0
  • 1z-index 開啟定位以后。z-index:1;數(shù)越大層級(jí)越高。 層級(jí)z軸。父元素層級(jí)比子元素高,但是父元素也...
    叫我老村長閱讀 389評(píng)論 0 0
  • 1.本課對(duì)我印象最深的: (1)第一組同學(xué)講課的方式,快,精,準(zhǔn)。還存有“狠",不給同學(xué)們留一點(diǎn)緩沖的空間。 (2...
    口服閱讀 243評(píng)論 0 0
  • 碧海吞紅日, 海鷗驅(qū)暮歸。 清風(fēng)吹臉畔, 兒女喚君回。
    蓮臺(tái)齊緣閱讀 163評(píng)論 5 20

友情鏈接更多精彩內(nèi)容