• 写一个vue的滚动条插件


    组件源码如下: vue-scroll.vue

    <template>
        <div class="vue-scroll" ref="vueScrollW">
            <div class="vue-scroll-w"  ref="vueScroll" >
                <div class="vue-scroll-c" :style="{cWidth}">
                    <slot></slot>
                </div>
            </div>
            <div class="vue-scrollbar" v-if="rate < 1">
                <div class="vue-scrollbar-thumb" 
                :style="{height:thumbH,top:thumbTop}"
                @mousedown="onmousedown"
                @mouseup="onmouseup"
                ></div>
            </div>
        </div>
    </template>
    
    <script>
    
    
    
    export default {
        name:"vue-scroll",
        data(){
            return {
                thumb:0,
                top:0,
                rate:2,
                moveTop:null,
                isDrag:false,
                cw:10,
                observer:null
            }
        },
        computed:{
            thumbH(){
                return this.thumb + "px";
            },
            thumbTop(){
                return this.top + "px";
            },
            cWidth(){
                return this.cw + "%";
            }
          
        },
        updated(){
            if(!window.MutationObserver){
                this.refresh();
            }
        },
        mounted(){
            var me = this;
            me.$refs.vueScroll.addEventListener("scroll",me.onscroll.bind(me));
            window.addEventListener("mouseup",me.onmouseup.bind(me));
            window.addEventListener("mousemove",me.onmousemove.bind(me));
    
           if(window.MutationObserver){
               //MutationObserver 最低只兼容 ie11 
                me.observer = new window.MutationObserver(me.mutationCallback.bind(me));
                me.observer.observe(me.$refs.vueScroll, {
                    attributes: true,
                    childList: true,
                    subtree: true
                });
           }
           
            me.refresh();
        },
        methods:{
            mutationCallback(mutationsList){
                this.refresh();
            },
            onscroll(){
                this.top = this.$refs.vueScroll.scrollTop * this.rate; //计算滚动条所在的高度
                if(this.rate < 1){
                    this.eventTrigger(this.top);
                }
            },
            refresh(){
                var me = this;
                var vueScroll = me.$refs.vueScroll;
                var rate =  vueScroll.clientHeight / vueScroll.scrollHeight; //滚动条高度的比例,也是滚动条top位置的比例
                me.rate = rate;
                if(rate < 1){
                    //需要出现滚动条,并计算滚动条的高度
                    me.thumb = rate * vueScroll.clientHeight;  //滚动条的 bar 的高度
                    //计算出原生的滚动条的宽度
                    var w = me.$refs.vueScrollW.clientWidth;
                    //根据比例,转换为内容的百分比
                    me.cw =  w/vueScroll.clientWidth *100;
                }else{
                    //不需要出现滚动条
                     me.thumb = 0;
                     me.cw = 10;
                }
            },
       
            onmousedown(){
                this.isDrag = true;
                this.moveTop = null;
            },
            onmouseup(){
               this.isDrag = false;
            },
            onmousemove(e){
                if(this.isDrag){
                    if(this.moveTop !== null){
                        var speed = e.screenY -  this.moveTop;
                        var top = this.top + speed;
                       this.scrollThumb(top);
                    }
                    this.moveTop = e.screenY;
                    e.preventDefault();
                }
                
            },
            scrollThumb(top){
                if(top < 0 ){
                    top = 0;
                    
                }
                if(top > this.$refs.vueScroll.clientHeight-this.thumb){
                    top = this.$refs.vueScroll.clientHeight-this.thumb;
                    
                }
                
                this.$refs.vueScroll.scrollTop = top/this.rate;
                this.top = top;
            },
            eventTrigger(top){
                if(top === 0){
                    this.$emit("reachTop"); //到达顶部
                }
                if(top === this.$refs.vueScroll.clientHeight-this.thumb){
                    this.$emit("reachBottom"); //到达底部与
                }
                this.$emit("vuescroll",this.$refs.vueScroll.scrollTop,this.top);//返回内容滚动的高度 和  滚动条所在的高度
            },
            scrollTo(scrollTop){
                //对外的api,滚动的内容的哪里
                 this.$refs.vueScroll.scrollTop = scrollTop;
                 this.$nextTick(()=>{
                     this.onscroll();
                 })
            }
        },
        destroyed(){
            var me = this;
            me.$refs.vueScroll && me.$refs.vueScroll.removeEventListener("scroll",me.onscroll.bind(me));
            window.removeEventListener("mouseup",me.onmouseup.bind(me));
            window.removeEventListener("mousemove",me.onmousemove.bind(me));
            me.observer&&me.observer.disconnect();
        }
    }
    </script>
    
    <style lang="scss" scoped>
    .vue-scroll{
        height: 100%;
         100%;
        overflow: hidden;
        position: relative;
        .vue-scroll-w{
             1000%;
            height: 100%;
            overflow: auto;
            .vue-scroll-c{
               position: relative;
                10%;
            }
        }
        .vue-scrollbar{
            position: absolute;
            z-index: 1;
            right: 0;
            top: 0;
             4px;
            height: 100%;
            background: #EEEEEE;
            opacity: 0.6;
            .vue-scrollbar-thumb{
                position: absolute;
                top: 0;
                right: 0;
                 4px;
                border-radius: 4px;
                background: #D3D3D3;
                &:hover{
                    background: #bbb;
                }
                &:active{
                    background: #aaa;
                }
            }
        }
    }
    </style>
    

      

      

    使用:

    <template>
        <div class="scroll">
            <vueScroll>
                <ul>
                    <li v-for="item in 60" :key="item">{{item}}</li>
                </ul>
            </vueScroll>
        </div>
    </template>
    
    <script>
    import vueScroll from "@/components/vue-scroll.vue"
    export default {
        data(){
            return {
                count:60
            }
        },
        components:{
            vueScroll
        },
        mounted(){
        
        }
    }
    </script>
    
    <style lang="less" scoped>
    .scroll{
         400px;
        height: 600px;
        margin: 0 auto;
        border: 1px solid red;
        ul{
            li{
                line-height: 30px;
                border-bottom: 1px solid #ddd;
            }
        }
    }
    </style>
    

      

  • 相关阅读:
    JS实现延迟载入图片
    三星指纹识别新专利:手势打开不同应用
    与计算机之间的另一种沟通方式 ——“手势识别”
    手写数字识别系统之图像分割
    机器学习实战八大分类器识别树叶带源码
    构建CTC语音识别解码网络
    MFC CListCtrl 条目取消选中
    C++ 将输入的字符串中英文大写字母改成对应小写字母,并且过滤掉非英文字母字符
    C++遍历SQLite数据库下的所有表名 .
    MFC 操作注册表 Open QueryValue等
  • 原文地址:https://www.cnblogs.com/muamaker/p/11203660.html
Copyright © 2020-2023  润新知