基于better-scroll的picker组件实现

这里再安利一下better-scroll这个组件库,该库的源代码结构清晰,借鉴了vue源码的组织形式。better-scroll提供的各功能模块相互独立,易于阅读,对初学者非常友好,建议学习一下。
另外,我们可以借助better-scroll提供的功能封装出更为复杂的组件。这里要说的picker选择器组件就是基于better-scroll提供的特性实现的。


实现原理

这里主要借助better-scroll提供的wheel属性,利用该属性并配合相应的html结构以及css样式可以很简单的实现选择器组件。

<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', () => {
                //滚动完成之后获取当前选取的索引值
                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>

以上代码实现的效果图如下所示,第一行即为当前选中的选项,我们接下来要做的事情就是给选中的选项设计样式。


image

样式设计

<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', () => {
                //滚动完成之后获取当前选取的索引值
                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>

以上代码实现的效果如下图所示,这里只给出了简单的原理以及演示,具体实现可根据自己的实际情况设计。


image

扩展

这里只演示了单列选择器组件,相对来说简单,我们在开发时常遇到的情形是多列的情况,再复杂就是各列存在联动关系。至于多列的设计,这里只需要创建多个better-scroll的实例即可。若存在多列联动的情形,需要根据滚动情况动态的输入相应了list,这里不再对详细设计做赘述。

总结

基于better-scroll还可以设计出很多复杂实用的组件,在后续会不断总结。。。。。

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
平台声明:文章内容(如有图片或视频亦包括在内)由作者上传并发布,文章内容仅代表作者本人观点,简书系信息发布平台,仅提供信息存储服务。

推荐阅读更多精彩内容

  • 1、通过CocoaPods安装项目名称项目信息 AFNetworking网络请求组件 FMDB本地数据库组件 SD...
    阳明AI阅读 16,025评论 3 119
  • 今天早上,我
    金铖天清阅读 172评论 0 0
  • 1z-index 开启定位以后。z-index:1;数越大层级越高。 层级z轴。父元素层级比子元素高,但是父元素也...
    叫我老村长阅读 354评论 0 0
  • 1.本课对我印象最深的: (1)第一组同学讲课的方式,快,精,准。还存有“狠",不给同学们留一点缓冲的空间。 (2...
    口服阅读 239评论 0 0
  • 碧海吞红日, 海鸥驱暮归。 清风吹脸畔, 儿女唤君回。
    莲台齐缘阅读 154评论 5 20