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

<template>
<div class="vue-scroll" ref="vueScrollW">
<div class="vue-scroll-w" ref="vueScroll" >
<div class="vue-scroll-c" :style="{width: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%;
width: 100%;
overflow: hidden;
position: relative;
.vue-scroll-w{
width: 1000%;
height: 100%;
overflow: auto;
.vue-scroll-c{
position: relative;
width: 10%;
}
}
.vue-scrollbar{
position: absolute;
z-index: 1;
right: 0;
top: 0;
width: 4px;
height: 100%;
background: #EEEEEE;
opacity: 0.6;
.vue-scrollbar-thumb{
position: absolute;
top: 0;
right: 0;
width: 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{
width: 400px;
height: 600px;
margin: 0 auto;
border: 1px solid red;
ul{
li{
line-height: 30px;
border-bottom: 1px solid #ddd;
}
}
}
</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. 基于栈的指令集与基于寄存器的指令集的区别,JVM指令集实例

    现代JVM在执行Java代码的时候,通常都会将解释执行与编译执行两者结合起来 所谓解释执行,就是通过解释器来读取字节码,遇到相应的指令就去执行该指令. 所谓编译执行,就是通过即时编译器(Just In ...

  2. GB28181技术基础之1 - SIP协议

    SIP 协议,即 会话初始协议(Session Initiation Protocol),是一个应用层的 点对点协议,用于初始.管理和终止网络中的语音和视频会话,是 GB28181 的核心之一. 按照 ...

  3. CopyOnWrite 思想及在 Java 并发包中的具体体现

    读多写少的场景下引发的问题? 假设现在我们的内存里有一个 ArrayList,这个 ArrayList 默认情况下肯定是线程不安全的,要是多个线程并发读和写这个 ArrayList 可能会有问题. 那 ...

  4. 005 DOM02

    在上一篇DOM的基础上,继续案例的实践. 一:案例 1.禁用文本框 <!DOCTYPE html> <html lang="en"> <head> ...

  5. Spring cloud微服务安全实战-6-7jwt改造总结

    限流的改造. 同样注意,不要声明成Spring的Bean 在上面声明Rateliiter 如果能获取到权限继续往下走,没权限就返回,to many request的错误信息. 加到过滤器链上 加载Sp ...

  6. 函数和宏实现打印的增强myprintf

    函数和宏实现打印的增强

  7. 【Mac】 /usr/local 文件夹权限问题

    修改文件夹权限 sudo chown -R $(whoami) /usr/local/ 如果失败提示Operation not permitted 或其他权限不足,则需要关闭Rootless Root ...

  8. Linux系统调优——内核相关参数(五)

    修改内核参数有3种办法:一种临时修改,两种永久修改. 临时修改是使用sysctl [选项] [参数名=值]命令:永久修改是修改/etc/sysctl.conf文件或修改/proc/sys/目录下的对应 ...

  9. 使用idea创建简单的webservice服务

     New project: 生成HelloWorld.wsdl: 配置好tomcat后还需要加入 Axis 的库: 启动后,访问http://localhost:8080/services: 点击He ...

  10. DBGrid中插入DateTimePicker

    DateTimePicker inside a DBGrid Here's how to place a TDateTimePicker into a DBGrid. Create visually ...