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

  1. <template>
  2. <div class="vue-scroll" ref="vueScrollW">
  3. <div class="vue-scroll-w" ref="vueScroll" >
  4. <div class="vue-scroll-c" :style="{width:cWidth}">
  5. <slot></slot>
  6. </div>
  7. </div>
  8. <div class="vue-scrollbar" v-if="rate < 1">
  9. <div class="vue-scrollbar-thumb"
  10. :style="{height:thumbH,top:thumbTop}"
  11. @mousedown="onmousedown"
  12. @mouseup="onmouseup"
  13. ></div>
  14. </div>
  15. </div>
  16. </template>
  17.  
  18. <script>
  19.  
  20. export default {
  21. name:"vue-scroll",
  22. data(){
  23. return {
  24. thumb:0,
  25. top:0,
  26. rate:2,
  27. moveTop:null,
  28. isDrag:false,
  29. cw:10,
  30. observer:null
  31. }
  32. },
  33. computed:{
  34. thumbH(){
  35. return this.thumb + "px";
  36. },
  37. thumbTop(){
  38. return this.top + "px";
  39. },
  40. cWidth(){
  41. return this.cw + "%";
  42. }
  43.  
  44. },
  45. updated(){
  46. if(!window.MutationObserver){
  47. this.refresh();
  48. }
  49. },
  50. mounted(){
  51. var me = this;
  52. me.$refs.vueScroll.addEventListener("scroll",me.onscroll.bind(me));
  53. window.addEventListener("mouseup",me.onmouseup.bind(me));
  54. window.addEventListener("mousemove",me.onmousemove.bind(me));
  55.  
  56. if(window.MutationObserver){
  57. //MutationObserver 最低只兼容 ie11
  58. me.observer = new window.MutationObserver(me.mutationCallback.bind(me));
  59. me.observer.observe(me.$refs.vueScroll, {
  60. attributes: true,
  61. childList: true,
  62. subtree: true
  63. });
  64. }
  65.  
  66. me.refresh();
  67. },
  68. methods:{
  69. mutationCallback(mutationsList){
  70. this.refresh();
  71. },
  72. onscroll(){
  73. this.top = this.$refs.vueScroll.scrollTop * this.rate; //计算滚动条所在的高度
  74. if(this.rate < 1){
  75. this.eventTrigger(this.top);
  76. }
  77. },
  78. refresh(){
  79. var me = this;
  80. var vueScroll = me.$refs.vueScroll;
  81. var rate = vueScroll.clientHeight / vueScroll.scrollHeight; //滚动条高度的比例,也是滚动条top位置的比例
  82. me.rate = rate;
  83. if(rate < 1){
  84. //需要出现滚动条,并计算滚动条的高度
  85. me.thumb = rate * vueScroll.clientHeight; //滚动条的 bar 的高度
  86. //计算出原生的滚动条的宽度
  87. var w = me.$refs.vueScrollW.clientWidth;
  88. //根据比例,转换为内容的百分比
  89. me.cw = w/vueScroll.clientWidth *100;
  90. }else{
  91. //不需要出现滚动条
  92. me.thumb = 0;
  93. me.cw = 10;
  94. }
  95. },
  96.  
  97. onmousedown(){
  98. this.isDrag = true;
  99. this.moveTop = null;
  100. },
  101. onmouseup(){
  102. this.isDrag = false;
  103. },
  104. onmousemove(e){
  105. if(this.isDrag){
  106. if(this.moveTop !== null){
  107. var speed = e.screenY - this.moveTop;
  108. var top = this.top + speed;
  109. this.scrollThumb(top);
  110. }
  111. this.moveTop = e.screenY;
  112. e.preventDefault();
  113. }
  114.  
  115. },
  116. scrollThumb(top){
  117. if(top < 0 ){
  118. top = 0;
  119.  
  120. }
  121. if(top > this.$refs.vueScroll.clientHeight-this.thumb){
  122. top = this.$refs.vueScroll.clientHeight-this.thumb;
  123.  
  124. }
  125.  
  126. this.$refs.vueScroll.scrollTop = top/this.rate;
  127. this.top = top;
  128. },
  129. eventTrigger(top){
  130. if(top === 0){
  131. this.$emit("reachTop"); //到达顶部
  132. }
  133. if(top === this.$refs.vueScroll.clientHeight-this.thumb){
  134. this.$emit("reachBottom"); //到达底部与
  135. }
  136. this.$emit("vuescroll",this.$refs.vueScroll.scrollTop,this.top);//返回内容滚动的高度 和 滚动条所在的高度
  137. },
  138. scrollTo(scrollTop){
  139. //对外的api,滚动的内容的哪里
  140. this.$refs.vueScroll.scrollTop = scrollTop;
  141. this.$nextTick(()=>{
  142. this.onscroll();
  143. })
  144. }
  145. },
  146. destroyed(){
  147. var me = this;
  148. me.$refs.vueScroll && me.$refs.vueScroll.removeEventListener("scroll",me.onscroll.bind(me));
  149. window.removeEventListener("mouseup",me.onmouseup.bind(me));
  150. window.removeEventListener("mousemove",me.onmousemove.bind(me));
  151. me.observer&&me.observer.disconnect();
  152. }
  153. }
  154. </script>
  155.  
  156. <style lang="scss" scoped>
  157. .vue-scroll{
  158. height: 100%;
  159. width: 100%;
  160. overflow: hidden;
  161. position: relative;
  162. .vue-scroll-w{
  163. width: 1000%;
  164. height: 100%;
  165. overflow: auto;
  166. .vue-scroll-c{
  167. position: relative;
  168. width: 10%;
  169. }
  170. }
  171. .vue-scrollbar{
  172. position: absolute;
  173. z-index: 1;
  174. right: 0;
  175. top: 0;
  176. width: 4px;
  177. height: 100%;
  178. background: #EEEEEE;
  179. opacity: 0.6;
  180. .vue-scrollbar-thumb{
  181. position: absolute;
  182. top: 0;
  183. right: 0;
  184. width: 4px;
  185. border-radius: 4px;
  186. background: #D3D3D3;
  187. &:hover{
  188. background: #bbb;
  189. }
  190. &:active{
  191. background: #aaa;
  192. }
  193. }
  194. }
  195. }
  196. </style>

  

  

使用:

  1. <template>
  2. <div class="scroll">
  3. <vueScroll>
  4. <ul>
  5. <li v-for="item in 60" :key="item">{{item}}</li>
  6. </ul>
  7. </vueScroll>
  8. </div>
  9. </template>
  10.  
  11. <script>
  12. import vueScroll from "@/components/vue-scroll.vue"
  13. export default {
  14. data(){
  15. return {
  16. count:60
  17. }
  18. },
  19. components:{
  20. vueScroll
  21. },
  22. mounted(){
  23.  
  24. }
  25. }
  26. </script>
  27.  
  28. <style lang="less" scoped>
  29. .scroll{
  30. width: 400px;
  31. height: 600px;
  32. margin: 0 auto;
  33. border: 1px solid red;
  34. ul{
  35. li{
  36. line-height: 30px;
  37. border-bottom: 1px solid #ddd;
  38. }
  39. }
  40. }
  41. </style>

  

写一个vue的滚动条插件的更多相关文章

  1. 分享一个自己写的vue多语言插件smart-vue-i18n

    前言 目前有比较成熟的方案(vue-i18n)了解了下,并且实用了一下感觉对于我在使用的项目来说略显臃肿,功能比较多,所以压缩的会比较大,在移动端不太适合所以自己花一天时间撸了一个vue多语言插件,压 ...

  2. 写一个vue组件

    写一个vue组件 我下面写的是以.vue结尾的单文件组件的写法,是基于webpack构建的项目.如果还不知道怎么用webpack构建一个vue的工程的,可以移步到vue-cli. 一个完整的vue组件 ...

  3. 大前端工程化之写一个简单的webpack插件

    今天写一个简单的webpack插件,来学习一下webpack插件 webpack插件机制可以使开发者在webpack构建过程中加入自己的行为,来针对自己项目中的一些需求做一些定制化 首先我们得知道一个 ...

  4. 写一个Vue loading 插件

    什么是vue插件? 从功能上说,插件是为Vue添加全局功能的一种机制,比如给Vue添加一个全局组件,全局指令等: 从代码结构上说,插件就是一个必须拥有install方法的对象,这个方法的接收的第一个参 ...

  5. 如何优雅的写一个Vue 的弹框

    写Vue或者是react 都会遇见弹框的问题.也尝试了多种办法来写弹框,一直都不太满意,今天特地看了一下 Element UI 的源码,模仿着写了一个简易版. 大概有一下几个问题: 1.弹框的层级问题 ...

  6. 使用 js,自己写一个简单的滚动条

    当我们给元素加上 overflow: auto;  的时候,就会出现滚动条,然而浏览的不同,滚动条的样式大不一样,有些甚至非常丑. 于是就想着自己写一个滚动条,大概需要弄清楚一下这几个点: 1.滚动条 ...

  7. 面试题:你能写一个Vue的双向数据绑定吗?

    在目前的前端面试中,vue的双向数据绑定已经成为了一个非常容易考到的点,即使不能当场写出来,至少也要能说出原理.本篇文章中我将会仿照vue写一个双向数据绑定的实例,名字就叫myVue吧.结合注释,希望 ...

  8. 学习如何写一个vue插件【入门篇】

    #### 疑答 1.市面上已经有那么多插件可用,为什么还要造轮子?学习.借鉴思想.应用到开发 2.能否在项目中使用?与网上插件使用相同   更新维护问题怎么解决? 自身动力,使用者反馈等 #### 准 ...

  9. 写一个简单的JQ插件(例子)

    虽然现在 vue angular react 当道啊但是那 JQ还是有一席之地很多很多的小单位啊.其实还会用到 我也放一个例子吧虽然我也不是很肯定有没有人写的比我更好啊但是我相信 我这个还是蛮实用的 ...

随机推荐

  1. delphi 运算符重载

    譬如上面的 record 可以这样声明: type   TMyRec = record     name: string;     age: Word;     class operator Grea ...

  2. fingerprint for the ECDSA key

    验证  fingerprint for the ECDSA key ssh-keygen -t  ecdsa  -f ssh_host_ecdsa_key 在B上ssh A ,得到A的fingerpr ...

  3. transition 滑动动画

    html: <!-- 组件会在 `currentTabComponent` 改变时改变 --> <transition name="slide" mode=&qu ...

  4. 【转载】 漫谈Code Review的错误实践

    原文地址: https://www.cnblogs.com/chaosyang/p/code-review-wrong-practices.html ------------------------- ...

  5. sql中去除重复的数据 select distinct * from table

    总的思路就是先找出表中重复数据中的一条数据,插入临时表中,删除所有的重复数据,然后再将临时表中的数据插入表中.所以重点是如何找出重复数据中的一条数据,有三种情况 1.重复数据完全一样,使用distin ...

  6. invalid application of ‘sizeof’ to incomplete type

    sizeof 后面所跟的数据类型没有定义,或者找不到定义的地方 eg: 头文件中定义结构体如下: struct PersonaL{ char name[]; int  age; }; 但是在cpp中使 ...

  7. python多线程中join()的理解

    在 Python 的多线程编程中,经常碰到 thread.join()这样的代码.那么今天咱们用实际代码来解释一下 join 函数的作用. 第一,当一个进程启动之后,会默认产生一个主线程,因为线程是程 ...

  8. 【Mac】解决macos安装升级时报错安装所选更新时发生错误的问题

    1 系统更新macjave 更新一直失败: 2  解决方法为:重新启动Mac,并按住Command+R进入恢复模式,找到Terminal后输入csrutil disable,然后重启Mac,再次下载并 ...

  9. Qt编写气体安全管理系统25-位置调整

    一.前言 位置调整功能,以前是直接写在设备按钮这个自定义控件类中,核心就是安装事件过滤器,识别鼠标按下.鼠标移动.鼠标松开,这三个event,做出相应的处理即可,后面发现这个功能其实很多自定义控件或者 ...

  10. Qt编写自定义控件70-扁平化flatui

    一.前言 对于现在做前端开发人员来说,FlatUI肯定不陌生,最近几年扁平化的设计越来越流行,大概由于现在PC端和移动端的设备的分辨率越来越高,扁平化反而看起来更让人愉悦,而通过渐变色产生的质感色彩反 ...