vue3系列:vue3.0自定义虚拟滚动条V3Scroll|vue3模拟滚动条组件

vue

基于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模拟滚动条组件 的全部内容, 来源链接: utcz.com/z/376282.html

回到顶部