快捷搜索:  汽车  科技

vue弹出框组件生命周期(超精简Vue.js桌面端自定义滚动条组件VScroll)

vue弹出框组件生命周期(超精简Vue.js桌面端自定义滚动条组件VScroll)<!-- //VScroll 自定义滚动条模板 --> <template> <div class="vui__scrollbar" ref="ref__box" @mouseenter="handleMouseEnter" @mouseleave="handleMouseLeave" v-resize="handleResize"> <div :class="['vscroll__wrap' {native: native}]" ref="ref__wrap" @scroll="handleScroll"> <div class="vscroll__view&

前几天有给大家分享一个Vue自定义弹框组件VLayer。今天再给大家分享一个最近开发的Vue PC端自定义滚动条组件VScroll。

vue弹出框组件生命周期(超精简Vue.js桌面端自定义滚动条组件VScroll)(1)

vue.js自定义pc端弹出框组件VLayer

v-scroll 基于vue2.x构建的轻量级桌面端自定义滚动条美化。支持是否原生滚动条、自动隐藏、滚动条大小及颜色等功能。

vue弹出框组件生命周期(超精简Vue.js桌面端自定义滚动条组件VScroll)(2)

vue弹出框组件生命周期(超精简Vue.js桌面端自定义滚动条组件VScroll)(3)

在组件设计开发之初借鉴了 饿了么el-scrollbar、Vuebar 等组件设计思想。

vue弹出框组件生命周期(超精简Vue.js桌面端自定义滚动条组件VScroll)(4)

vue弹出框组件生命周期(超精简Vue.js桌面端自定义滚动条组件VScroll)(5)

通过简单的标签式调用<v-scroll>...</v-scroll>及自定义参数(native|autohide|size|color) 即可快速生成一个漂亮的替代原生的滚动条。

快速引入

// 在main.js中引入 import Vue from 'vue'; import VScroll from './components/vscroll' Vue.use(VScroll)使用组件

注意:在v-scroll外层需要设置容器宽度或高度。

<v-scroll :native="true"> <img src="https://cn.vuejs.org/images/logo.png" /> <p>这里是内容信息!这里是内容信息!这里是内容信息...</p> </v-scroll> <v-scroll autohide size="12" color="#999"> <img src="https://cn.vuejs.org/images/logo.png" /> <p>这里是内容信息!这里是内容信息!这里是内容信息...</p> </v-scroll>

vue弹出框组件生命周期(超精简Vue.js桌面端自定义滚动条组件VScroll)(6)

vue弹出框组件生命周期(超精简Vue.js桌面端自定义滚动条组件VScroll)(7)

emmm~~,看到了这里,是不是觉得效果还行。基本能符合自定义滚动条需求。

实现过程

在components目录下新建vscroll目录,并新建vscroll.vue组件模板。

vue弹出框组件生命周期(超精简Vue.js桌面端自定义滚动条组件VScroll)(8)

<!-- //VScroll 自定义滚动条模板 --> <template> <div class="vui__scrollbar" ref="ref__box" @mouseenter="handleMouseEnter" @mouseleave="handleMouseLeave" v-resize="handleResize"> <div :class="['vscroll__wrap' {native: native}]" ref="ref__wrap" @scroll="handleScroll"> <div class="vscroll__view"> <slot /> </div> </div> <!-- //滚动条 --> <div :class="['vscroll__bar vertical' {ishide: !isShow}]" @mousedown="handleClickTrack($event 0)" :style="{'width': parseInt(size)>=0 ? parseInt(size) 'px' : ''}"> <div class="vscroll__thumb" ref="ref__barY" :style="{'background': color 'height': barHeight 'px'}" @mousedown="handleDragThumb($event 0)"></div> </div> <div :class="['vscroll__bar horizontal' {ishide: !isShow}]" @mousedown="handleClickTrack($event 1)" :style="{'height': parseInt(size)>=0 ? parseInt(size) 'px' : ''}"> <div class="vscroll__thumb" ref="ref__barX" :style="{'background': color 'width': barWidth 'px'}" @mousedown="handleDragThumb($event 1)"></div> </div> </div> </template>

vue自定义指令监听元素/DOM尺寸变化。

Vue.directive('resize' { bind(el binding) { let width = '' height = ''; function get() { const style = document.defaultView.getComputedStyle(el); if (width !== style.width || height !== style.height) { binding.value({width height}); } width = style.width; height = style.height; } el.__vueReize__ = setInterval(get 200); } unbind(el) { clearInterval(el.__vueReize__); } });

<script> export default { props: { // 是否显示原生滚动条 native: Boolean // 是否自动隐藏滚动条 autohide: Boolean // 滚动条尺寸 size: { type: [Number String] default: '' } // 滚动条颜色 color: String } data() { return { barWidth: 0 // 滚动条宽度 barHeight: 0 // 滚动条高度 ratioX: 1 // 滚动条水平偏移率 ratioY: 1 // 滚动条垂直偏移率 isTaped: false // 鼠标光标是否按住滚动条 isHover: false // 鼠标光标是否悬停在滚动区 isShow: !this.autohide // 是否显示滚动条 } } mounted() { this.$ref__box = this.$refs.ref__box this.$ref__wrap = this.$refs.ref__wrap this.$ref__barY = this.$refs.ref__barY this.$ref__barX = this.$refs.ref__barX this.$nextTick(this.updated) } // 监听元素/DOM尺寸变化 directives: { 'resize': { bind: function(el binding) { let width = '' height = ''; function get() { const elStyle = el.currentStyle ? el.currentStyle : document.defaultView.getComputedStyle(el null); if (width !== elStyle.width || height !== elStyle.height) { binding.value({width height}); } width = elStyle.width; height = elStyle.height; } el.__vueReize__ = setInterval(get 16); } unbind: function(el) { clearInterval(el.__vueReize__); } } } methods: { // 鼠标移入 handleMouseEnter() { this.isHover = true this.isShow = true this.updated() } // 鼠标移出 handleMouseLeave() { this.isHover = false this.isShow = false } // 拖动滚动条 handleDragThumb(e index) { let _this = this this.isTaped = true let c = {} document.onselectstart = () => false if(index == 0) { c.dragY = true c.clientY = e.clientY }else { c.dragX = true c.clientX = e.clientX } domUtils.on(document 'mousemove' function(evt) { if(_this.isTaped) { if(c.dragY) { _this.$ref__wrap.scrollTop = (evt.clientY - c.clientY) * _this.ratioY _this.$ref__barY.style.transform = `translateY(${_this.$ref__wrap.scrollTop / _this.ratioY}px)` c.clientY = evt.clientY } if(c.dragX) { _this.$ref__wrap.scrollLeft = (evt.clientX - c.clientX) * _this.ratioX _this.$ref__barX.style.transform = `translateX(${_this.$ref__wrap.scrollLeft / _this.ratioX}px)` c.clientX = evt.clientX } } }) domUtils.on(document 'mouseup' function() { _this.isTaped = false document.onselectstart = null if(!_this.isHover && _this.autohide) { _this.isShow = false } // ... }) } // 点击滚动槽 handleClickTrack(e index) { if(index == 0) { this.$ref__wrap.scrollTop = (Math.abs(e.target.getBoundingClientRect().top - e.clientY) - this.$ref__barY.offsetHeight / 2) * this.ratioY this.$ref__barY.style.transform = `translateY(${this.$ref__wrap.scrollTop / this.ratioY}px)` } if(index == 1) { this.$ref__wrap.scrollLeft = (Math.abs(e.target.getBoundingClientRect().left - e.clientX) - this.$ref__barX.offsetWidth / 2) * this.ratioX this.$ref__barX.style.transform = `translateX(${this.$ref__wrap.scrollLeft / this.ratioX}px)` } } // 更新滚动区 updated() { if(this.native) return // 垂直滚动条 if(this.$ref__wrap.scrollHeight > this.$ref__wrap.offsetHeight) { this.barHeight = this.$ref__box.offsetHeight **2 / this.$ref__wrap.scrollHeight this.ratioY = (this.$ref__wrap.scrollHeight - this.$ref__box.offsetHeight) / (this.$ref__box.offsetHeight - this.barHeight) this.$ref__barY.style.transform = `translateY(${this.$ref__wrap.scrollTop / this.ratioY}px)` }else { this.barHeight = 0 this.$ref__barY.style.transform = '' } // 水平滚动条 ... } // 滚动区元素/DOM尺寸改变 handleResize() { // ...更新滚动条 } // 鼠标滚动 handleScroll(e) { this.$emit('scroll' e) this.updated() } } } </script>

滚动到指定位置

vue弹出框组件生命周期(超精简Vue.js桌面端自定义滚动条组件VScroll)(9)

<p> <span class="vs__btn" @click="handleScrollTo('top')">滚动至顶部</span> <span class="vs__btn" @click="handleScrollTo('bottom')">滚动至底部</span> <span class="vs__btn" @click="handleScrollTo(150)">滚动至150px</span> </p> <v-scroll ref="vscrollRef" autohide size="8"> <img src="https://cn.vuejs.org/images/logo.png" /> <p>这里是内容信息!这里是内容信息!这里是内容信息...</p> </v-scroll> // 滚动到指定位置 handleScrollTo(val) { this.$refs.vscrollRef.scrollTo(val); }

监听scroll滚动事件

vue弹出框组件生命周期(超精简Vue.js桌面端自定义滚动条组件VScroll)(10)

<v-scroll @scroll="handleScroll"> <img src="https://cn.vuejs.org/images/logo.png" /> <p>这里是内容信息!这里是内容信息!这里是内容信息...</p> </v-scroll> // 监听滚动事件 handleScroll(e) { this.scrollTop = e.target.scrollTop // 判断滚动状态 if(e.target.scrollTop == 0) { this.scrollStatus = '到达顶部' } else if(e.target.scrollTop e.target.offsetHeight >= e.target.scrollHeight) { this.scrollStatus = '到达底部' }else { this.scrollStatus = '滚动中....' } }

vue弹出框组件生命周期(超精简Vue.js桌面端自定义滚动条组件VScroll)(11)

ok,以上就是基于vue.js模拟自定义滚动条组件。希望对大家有所帮助哈!

猜您喜欢: