基于Vue3.0构建PC桌面端自定义美化滚动条组件V3Scroll。

前段时间有分享一个Vue3 PC网页端弹窗组件,今天带来最新开发的Vue3.0版虚拟滚动条组件。

V3Scroll 使用vue3.x开发的轻量级自定义美化滚动条组件。功能效果基本和之前的vue2版保持一致。支持是否自动隐藏滚动条、自定义滚动条尺寸、颜色及层级等功能。

功能效果类似饿了么el-scrollbar组件。并且支持监听DOM尺寸改变,动态更新滚动条。

◆ 快速引入

main.js中全局引入滚动条v3scroll组件。

import { createApp } from 'vue'
import App from './App.vue'
import './index.css' // 引入滚动条组件v3scroll
import V3Scroll from './components/v3scroll' createApp(App).use(V3Scroll).mount('#app')

◆ 使用组件

通过  <v3-scroll>...</v3-scroll>  包裹内容块,即可快速实现一个精致的替代原生滚动条组件。

<!-- //自定义参数 -->
<v3-scroll size="12" color="#a96950" zIndex="2021">
<p>这里显示自定义内容!</p>
</v3-scroll> <!-- //scroll事件处理 -->
<v3-scroll @scroll="handleScroll">
<p>这里显示自定义内容!</p>
</v3-scroll>

◆ 编码实现

v3scroll支持如下参数自定义配置。

props: {
// 是否显示原生滚动条
native: Boolean,
// 是否自动隐藏滚动条
autohide: Boolean,
// 滚动条尺寸
size: { type: [Number, String], default: '' },
// 滚动条颜色
color: String,
// 滚动条层级
zIndex: null
},

v3scroll组件模板

<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" v-resize="handleResize">
<slot />
</div>
</div>
<div :class="['vscroll__bar vertical']" @mousedown="handleClickTrack($event, 0)" :style="{'width': parseInt(size)>=0 ? parseInt(size)+'px' : '', 'z-index': parseInt(zIndex)>=0 ? parseInt(zIndex) : ''}">
<div class="vscroll__thumb" ref="ref__barY" :style="{'background': color, 'height': barHeight+'px'}" @mousedown="handleDragThumb($event, 0)"></div>
</div>
<div :class="['vscroll__bar horizontal']" @mousedown="handleClickTrack($event, 1)" :style="{'height': parseInt(size)>=0 ? parseInt(size)+'px' : '', 'z-index': parseInt(zIndex)>=0 ? parseInt(zIndex) : ''}">
<div class="vscroll__thumb" ref="ref__barX" :style="{'background': color, 'width': barWidth+'px'}" @mousedown="handleDragThumb($event, 1)"></div>
</div>
</div>
</template>

注意:vue3.0中自定义指令directive和vue2中有些不一样。

// vue 2.x
const MyDirective = {
bind(el, binding, vnode, prevVnode) {},
inserted() {},
update() {},
componentUpdated() {},
unbind() {}
} // vue 3.x
const MyDirective = {
beforeMount(el, binding, vnode, prevVnode) {},
mounted() {},
beforeUpdate() {},
updated() {},
beforeUnmount() {},
unmounted() {}
}

下面介绍下在vue3.0中使用自定义指令。

// Vue3中自定义指令 - 监听DOM尺寸变化
directives: {
'resize': {
beforeMount: 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);
},
unmounted: function(el) {
clearInterval(el.__vueReize__);
}
}
}
/**
* @Desc Vue3.0虚拟滚动条组件V3Scroll
* @Time andy by 2021-01
* @About Q:282310962 wx:xy190310
*/
<script>
import { onMounted, ref, reactive, toRefs, nextTick } from 'vue'
import domUtils from './utils/dom'
export default {
props: {
// ...
}, /**
* Vue3.x自定义指令写法
*/
// 监听DOM尺寸变化
directives: {
'resize': {
beforeMount: 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);
},
unmounted: function(el) {
clearInterval(el.__vueReize__);
}
}
},
setup(props, context) {
const ref__box = ref(null)
const ref__wrap = ref(null)
const ref__barX = ref(null)
const ref__barY = ref(null) const data = reactive({
barWidth: 0, // 滚动条宽度
barHeight: 0, // 滚动条高度
ratioX: 1, // 滚动条水平偏移率
ratioY: 1, // 滚动条垂直偏移率
isTaped: false, // 鼠标光标是否按住滚动条
isHover: false, // 鼠标光标是否悬停在滚动区
isShow: !props.autohide, // 是否显示滚动条
}) onMounted(() => {
nextTick(() => {
updated()
})
}) // 鼠标滑入
const handleMouseEnter = () => {
data.isHover = true
data.isShow = true
updated()
} // 鼠标滑出
const handleMouseLeave = () => {
data.isHover = false
data.isShow = false
} // 拖动滚动条
const handleDragThumb = (e, index) => {
const elWrap = ref__wrap.value
const elBarX = ref__barX.value
const elBarY = ref__barY.value data.isTaped = true
let c = {}
// 阻止默认事件
domUtils.isIE() ? (e.returnValue = false, e.cancelBubble = true) : (e.stopPropagation(), e.preventDefault())
document.onselectstart = () => false if(index == 0) {
c.dragY = true
c.clientY = e.clientY
}else {
c.dragX = true
c.clientX = e.clientX
} // ...
} // 点击滚动槽
const handleClickTrack = (e, index) => {
// ...
} // 更新滚动区
const updated = () => {
if(props.native) return
const elBox = ref__box.value
const elWrap = ref__wrap.value
const elBarX = ref__barX.value
const elBarY = ref__barY.value let barSize = domUtils.getScrollBarSize() // 垂直滚动条
if(elWrap.scrollHeight > elWrap.offsetHeight) {
data.barHeight = elBox.offsetHeight **2 / elWrap.scrollHeight
data.ratioY = (elWrap.scrollHeight - elBox.offsetHeight) / (elBox.offsetHeight - data.barHeight)
elBarY.style.transform = `translateY(${elWrap.scrollTop / data.ratioY}px)`
// 隐藏系统滚动条
if(barSize) {
elWrap.style.marginRight = -barSize + 'px'
}
}else {
data.barHeight = 0
elBarY.style.transform = ''
elWrap.style.marginRight = ''
} // 水平滚动条
// ...
} // 滚动区元素/DOM尺寸改变
const handleResize = () => {
// 执行更新操作
} // ... return {
...toRefs(data),
ref__box, ref__wrap, ref__barX, ref__barY, handleMouseEnter, handleMouseLeave,
handleDragThumb, handleClickTrack,
updated, // ...
}
}
}
</script>

支持滚动至指定位置。

<v3-scroll ref="scrollRef">
<p>这里是内容信息!这里是内容信息!</p>
</v3-scroll> <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> setup() {
// 滚动到指定位置
const handleScrollTo = (val) => {
scrollRef.value.scrollTo(val)
}
}

OK,基于Vue3开发自定义模拟滚动条组件就分享到这里。希望大家能喜欢哈~

最后附上一个Vue3.0移动端弹框组件

vue3.0手机端弹层组件:https://www.cnblogs.com/xiaoyan2017/p/14210820.html

vue3系列:vue3.0自定义虚拟滚动条V3Scroll|vue3模拟滚动条组件的更多相关文章

  1. vue2.0 自定义 饼状图 (Echarts)组件

    1.自定义  图表  组件 Echarts.vue <!-- 自定义 echart 组件 --> <template> <div> <!-- echart表格 ...

  2. vue2.0 自定义 图片上传(UpLoader)组件

    1.自定义组件 UpLoader.vue <!-- 上传图片 组件 --> <template> <div class="vue-uploader"& ...

  3. vue3系列:vue3.0自定义弹框组件V3Popup|vue3.x手机端弹框组件

    基于Vue3.0开发的轻量级手机端弹框组件V3Popup. 之前有分享一个vue2.x移动端弹框组件,今天给大家带来的是Vue3实现自定义弹框组件. V3Popup 基于vue3.x实现的移动端弹出框 ...

  4. Android开发案例 - 自定义虚拟键盘

    所有包含IM功能的App(如微信, 微博, QQ, 支付宝等)都提供了Emoji表情之类的虚拟键盘,  如下图:    本文只着重介绍如何实现输入法键盘和自定义虚拟键盘的流畅切换, 而不介绍如何实现虚 ...

  5. WPF中实现自定义虚拟容器(实现VirtualizingPanel)

    WPF中实现自定义虚拟容器(实现VirtualizingPanel) 在WPF应用程序开发过程中,大数据量的数据展现通常都要考虑性能问题.有下面一种常见的情况:原始数据源数据量很大,但是某一时刻数据容 ...

  6. vue.js2.0 自定义组件初体验

    理解 组件(Component)是 Vue.js 最强大的功能之一.组件可以扩展 HTML 元素,封装可重用的代码.在较高层面上,组件是自定义元素, Vue.js 的编译器为它添加特殊功能.在有些情况 ...

  7. Spring 系列教程之自定义标签的解析

    Spring 系列教程之自定义标签的解析 在之前的章节中,我们提到了在 Spring 中存在默认标签与自定义标签两种,而在上一章节中我们分析了 Spring 中对默认标签的解析过程,相信大家一定已经有 ...

  8. React Native实战系列教程之自定义原生UI组件和VideoView视频播放器开发

    React Native实战系列教程之自定义原生UI组件和VideoView视频播放器开发   2016/09/23 |  React Native技术文章 |  Sky丶清|  4 条评论 |  1 ...

  9. 实战:ADFS3.0单点登录系列-ADFS3.0安装配置

    本文为系列第三章,主要讲下ADFS3.0的安装和配置.本文和前面的文章是一个系列,因此有些地方是有前后关联,比如本文中使用的通配符证书就是第二篇讲解的,因此需要连贯的进行阅读. 全文目录如下: 实战: ...

随机推荐

  1. C# 打开Excel文件

    方法一:(调用Excel的COM组件)       在项目中打开Add Reference对话框,选择COM栏,之后在COM列表中找到"Microsoft Excel 11.0 Object ...

  2. 24位PCM采样数据转成16位算法,已实现PCM转WAV在线工具源码支持24bits、16bits、8bits

    目录 算法来源 js版24位PCM转8位.16位代码 js版8位.16位PCM转成24位 附:浏览器控制台下载数据文件代码 相关实现 最近收到几个24位的PCM录音源文件,Recoder库原有的PCM ...

  3. 风炫安全web安全学习第三十节课 命令执行&代码执行基础

    风炫安全web安全学习第三十节课 命令执行&代码执行基础 代码执行&命令执行 RCE漏洞,可以让攻击者直接向后台服务器远程注入操作系统命令或者代码,从而控制后台系统. 远程系统命令执行 ...

  4. linux脚本错误: line *: [: missing `]',linux编写shell脚本时的注意点

    转载:https://www.cnblogs.com/bovenson/p/4548079.html 关于shell的一些注意点,粘贴自拉钩教育精选评论:测试开发核心技术 46 讲-->第6讲 ...

  5. laravel邮件发送

    laravel邮件发送 使用邮件发送类Mail 文本 静态方法 raw() 富文本 静态方法 send() 注:使用邮件发送必须有邮件账号,需要开启smtp协议,现在主流服务器都支持,smtp默认端口 ...

  6. SpringBoot项目,如何优雅的把接口参数中的空白值替换为null值?

    问题发生 我们公司代码生成的时候,查询列表统一都是使用了setEntity() ,查询写法如下: public List<BasReservoirArea> selectList(BasR ...

  7. 【Flutter】容器类组件之Scaffold、TabBar、底部导航

    前言 一个完整的路由页可能会包含导航栏.抽屉菜单(Drawer)以及底部Tab导航菜单等.Flutter Material组件库提供了一些现成的组件来减少开发任务.Scaffold是一个路由页的骨架, ...

  8. Js中函数式编程的理解

    函数式编程的理解 函数式编程是一种编程范式,可以理解为是利用函数把运算过程封装起来,通过组合各种函数来计算结果.函数式编程与命令式编程最大的不同其实在于,函数式编程关心数据的映射,命令式编程关心解决问 ...

  9. linux硬盘分区和fdisk命令

    分区的几个概念 硬盘分区有三种,主分区.扩展分区.逻辑分区.一个硬盘主分区至少有1个,最多4个,扩展分区可以没有,最多1个.且主分区+扩展分区总共不能超过4个.逻辑分区可以有若干个.在windows下 ...

  10. 私有镜像仓库Harbor基础介绍与部署

    企业级私有镜像仓库Harbor 一:介绍 Harbor,是一个英文单词,意思是港湾,港湾是干什么的呢,就是停放货物的,而货物呢,是装在集装箱中的,说到集装箱,就不得不提到Docker容器,因为dock ...