Vue自定义滚动条盒子

Posted viewts

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Vue自定义滚动条盒子相关的知识,希望对你有一定的参考价值。

应用开发过程中当web页面的内容过多时则会出现滚动条,而原生的滚动条的样式除了谷歌浏览器外其他的浏览器都不好修改,于是打算自己写一个容器组件,当内容过多时隐藏默认的滚动条显示自定义滚动条(只做了垂直滚动条,懒~)

先来看看如何引用这个滚动盒子(hd-scroll,注:"hd"是与我相关某个名字的简称)组件,先在app里面填充100个div:

1 <template>
2     <div class="container">
3         <div v-for="i in 100" :key="i"> i </div>
4     </div>
5 </template>

然后在把container容器的大小限制一下:

1 <style lang="scss" scoped>
2     .container 
3         background-color: whitesmoke;
4         width: 200px;
5         height: 400px;
6     
7 </style>

打开页面,可以看到浏览器右边出现了默认的滚动条,而且我们添加的div元素也超出了container范围。

技术图片

解决这个问题的一般方式是在样式里面添加“overflow:auto”属性,再来看一下效果:

技术图片

改善了许多,但是滚动条的样式却不好改变,于是现在引入hd-scroll组件:

 1 <template>
 2     <div class="container">
 3         <hd-scroll>
 4             <div v-for="i in 100" :key="i"> i </div>
 5         </hd-scroll>
 6     </div>
 7 </template>
 8 
 9 <script>
10 import hdScroll from ./components/hdScroll
11 
12 export default 
13     components: 
14         hdScroll
15         
16 
17 </script>
18 
19 <style lang="scss" scoped>
20     .container 
21         background-color: whitesmoke;
22         width: 200px;
23         height: 400px;
24     
25 </style>

在这里需要注意的是用<hd-scroll>标签来包裹住大量的要渲染的元素,同时删除overflow属性,添加了滚动盒子组件后的页面看起来或许是这个样子的:

技术图片

ps:鼠标的小黄点是录频工具的,不是页面自带的。。。

滚动盒子(hd-scroll)的实现方式如下:

  1 <template>
  2     <div class="hd-scroll scrollbox" ref="box" 
  3     @mousewheel.stop.prevent="handleMouseWheel" 
  4     @mouseenter="handleMouseEnter" 
  5     @mouseleave="handleMouseLeave">
  6         <transition name="fade">
  7             <div :class="[‘scrollbar‘,  force: force ]" ref="bar" 
  8             v-show="show" :style=" ‘height‘: barHeight + ‘px‘" 
  9             @mousedown="handleMouseDown"></div>
 10         </transition>
 11         <slot></slot>
 12     </div>
 13 </template>
 14 
 15 <script>
 16 export default 
 17     name: hdScroll,
 18     data() 
 19         return 
 20             box: undefined, // 自定义滚动条盒子
 21             bar: undefined, // 滚动条
 22             barHeight: 100, // 滚动条高度
 23             ratio: 1,       // 滚动条偏移率
 24             force: false,   // 滚动条是否被鼠标光标按住
 25             hover: false,   // 鼠标光标是否悬停在盒子上
 26             show: false     // 是否显示滚动条
 27         
 28     ,
 29     mounted() 
 30         this.box = this.$refs.box
 31         this.bar = this.$refs.bar
 32         // 滚动条全局可拖动
 33         document.addEventListener(mouseup, this.handleMouseUp)
 34         document.addEventListener(mousemove, this.handleMouseMove)
 35     ,
 36     methods: 
 37         /**
 38          * 鼠标滚轮事件
 39          * @param object e 事件
 40          */
 41         handleMouseWheel(e) 
 42             this.box.scrollTop -= e.wheelDelta / 4
 43             this.bar.style.transform = translateY( + (this.box.scrollTop + this.box.scrollTop / this.ratio) + px)
 44         ,
 45         /**
 46          * 鼠标按下
 47          * @param object e 事件
 48          */
 49         handleMouseDown(e) 
 50             if (e.target === this.bar) 
 51                 this.box.prevY = e.pageY
 52                 this.force = true
 53             
 54         ,
 55         /**
 56          * 鼠标按键释放
 57          */
 58         handleMouseUp() 
 59             this.force = false
 60             this.box.prevY = null
 61             if (!this.hover) 
 62                 this.show = false
 63             
 64         ,
 65         /**
 66          * 鼠标移动
 67          * @param object e 事件
 68          */
 69         handleMouseMove(e) 
 70             if (this.force) 
 71                 // 阻止默认选中事件(IE下无效)
 72                 e.preventDefault()
 73                 this.box.scrollTop += (e.pageY - this.box.prevY) * this.ratio
 74                 this.bar.style.transform = translateY( + (this.box.scrollTop + this.box.scrollTop / this.ratio) + px)
 75                 this.box.prevY = e.pageY
 76             
 77         ,
 78         /**
 79          * 鼠标光标进入盒子范围
 80          */
 81         handleMouseEnter() 
 82             this.hover = true
 83             if (this.box.scrollHeight > this.box.offsetHeight) 
 84                 // 修正进度条高度和位置(建议通过事件触发)
 85                 this.barHeight = this.box.offsetHeight ** 2 / this.box.scrollHeight
 86                 this.ratio = (this.box.scrollHeight - this.box.offsetHeight) / (this.box.offsetHeight - this.barHeight)
 87                 this.bar.style.transform = translateY( + (this.box.scrollTop + this.box.scrollTop / this.ratio) + px)
 88                 // 显示滚动条
 89                 this.$nextTick(() => this.show = true)
 90             
 91         ,
 92         /**
 93          * 鼠标光标离开盒子范围
 94          */
 95         handleMouseLeave() 
 96             this.hover = false
 97             if (!this.force) 
 98                 this.show = false
 99             
100         
101     
102 
103 </script>
104 
105 <style lang="scss" scoped>
106     // 滚动条宽度
107     $scrollbar-width: 8px;
108 
109     .scrollbox 
110         width: 100%;
111         height: 100%;
112         position: relative;
113         padding-right: $scrollbar-width;
114         overflow-y: hidden;
115     
116     .scrollbar 
117         width: $scrollbar-width;
118         height: 100%;
119         background-color: darkgray;
120         position: absolute;
121         right: 0;
122         border-radius: $scrollbar-width / 2;
123         &:hover 
124             background-color: gray;
125         
126         &.force 
127             background-color: gray;
128         
129     
130 
131     // Vue进入离开动画
132     .fade-enter-active, .fade-leave-active 
133         transition: opacity .5s;
134     
135     .fade-enter, .fade-leave-to 
136         opacity: 0;
137     
138 </style>

在谷歌里鼠标滚轮事件可使用deltaY来控制滚动,不过为了兼容ie,选择了使用wheelDelta来代替,它们之间的关系大约是wheelDelta == -4 * deltaY。在设置滚动条移动的过程中是通过CSS3属性transform,在低版本ie浏览器中可能无法运行,可以考虑使用style.top来代替,不过看网上大神们都是通过两个div容器来隐藏主默认的滚动条,实现方法如下:

 1 <!DOCTYPE html>
 2 <html lang="zh-CN">
 3 <head>
 4     <meta charset="UTF-8">
 5     <meta name="viewport" content="width=device-width, initial-scale=1.0">
 6     <meta http-equiv="X-UA-Compatible" content="ie=edge">
 7     <title>Document</title>
 8     <style>
 9         #app 
10             width: 200px;
11             height: 400px;
12         
13     </style>
14 </head>
15 <body>
16     <div id="app">
17         <div class="out-box">
18             <div class="inner-box">
19                 <div class="container">
20                     <div v-for="i in 100" :key="i"> i </div>
21                 </div>
22             </div>
23         </div>
24     </div>
25     <script src="./vue.min.js"></script>
26     <script>
27         new Vue(
28             el: #app
29         )
30     </script>
31 </body>
32 </html>

先设置好页面结构,在这里#app是宽度200px, 高度400px的容器,我们需要使内容不溢出的同时隐藏滚动条:

 1 .out-box 
 2     width: 100%;
 3     height: 100%;
 4     position: relative;
 5     overflow: hidden;
 6 
 7 
 8 .inner-box 
 9     width: 100%;
10     height: 100%;
11     position: absolute;
12     padding-right: 17px;
13     padding-bottom: 17px;
14     overflow: auto;
15 

只需要添加两个盒子属性就完成了,很简单吧

技术图片

源码下载(需要自己装包):https://files.cnblogs.com/files/viewts/hd-scroll.zip

以上是关于Vue自定义滚动条盒子的主要内容,如果未能解决你的问题,请参考以下文章

vue如何实现自定义滚动条

div 如何加滚动条

Vue中如何用鼠标滑轮进行横向滑动不显示滚动条

Vue中如何用鼠标滑轮进行横向滑动不显示滚动条

Vue练习六十:08_02_自定义滚动条(缺键盘左右箭头功能)

转载jquery 滚动条插件jquery.slimscroll.js