龙空技术网

Vue3.0系列:vue3定制美化滚动条组件v3scroll

web前端进阶 805

前言:

眼前大家对“js自动滚动条”大体比较注重,看官们都需要学习一些“js自动滚动条”的相关资讯。那么小编在网络上汇集了一些关于“js自动滚动条””的相关知识,希望小伙伴们能喜欢,同学们快快来了解一下吧!

今天给大家分享一个最新开发的Vue3自定义模拟滚动条组件v3scroll。

V3Scroll 基于vue3.0开发的轻量级PC端虚拟滚动条组件。支持是否自动隐藏、自定义大小、颜色及层叠等功能。

开发灵感来自于之前的vue2版自定义滚动条组件。借鉴了ElementPlus滚动条设计。

vue2.x自定义桌面端滚动条组件

v3scroll同样支持垂直/水平滚动条。并且在功能效果上和之前vue2版保持一致。

通过简单的<v3-scroll></v3-scroll>裹住内容块,即可快速生成一个精致的仿原生滚动条。

引入组件

在main.js中整体引入组件。

import { createApp } from 'vue'import App from './App.vue'import './index.css'// 引入滚动条组件v3scrollimport V3Scroll from './components/v3scroll'createApp(App).use(V3Scroll).mount('#app')
快速使用
<v3-scroll :native="true">	<img src="; style="max-width:100%;" />	<p>这里是内容信息!这里是内容信息!这里是内容信息!这里是内容信息!</p></v3-scroll>
<v3-scroll size="12px">	<img src="; style="height:180px" />    <img src="; style="height:180px" />	<p>这里是内容信息!这里是内容信息!这里是内容信息!这里是内容信息!</p></v3-scroll>
编码实现参数配置
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', {ishide: !isShow}]" @mousedown="handleClickTrack($event, 0)">            <div class="vscroll__thumb" ref="ref__barY" @mousedown="handleDragThumb($event, 0)"></div>        </div>        <div :class="['vscroll__bar horizontal', {ishide: !isShow}]" @mousedown="handleClickTrack($event, 1)">            <div class="vscroll__thumb" ref="ref__barX" @mousedown="handleDragThumb($event, 1)"></div>        </div>    </div></template>
v3scroll逻辑处理
<script>    import { onMounted, ref, reactive, toRefs, nextTick } from 'vue'    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,            })            // 鼠标滑入            const handleMouseEnter = () => {                data.isHover = true                data.isShow = true                updated()            }            // 鼠标滑出            const handleMouseLeave = () => {                data.isHover = false                if(!data.isTaped && props.autohide) {                    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)`                }else {                    data.barHeight = 0                    elBarY.style.transform = ''                    elWrap.style.marginRight = ''                }                // 水平滚动条                // ...            }            // 滚动区元素/DOM尺寸改变            const handleResize = () => {                updated()            }            // 鼠标滚动            const handleScroll = (e) => {                context.emit('scroll', e)                updated()            }            const scrollTo = (dir) => {                const elWrap = ref__wrap.value                const elBarY = ref__barY.value                nextTick(() => {                    elWrap.scrollTop = (dir == 'top') ? 0 : (dir == 'bottom') ? elWrap.scrollHeight : parseInt(dir)                    elBarY.style.transform = `translateY(${elWrap.scrollTop / data.ratioY}px)`                })            }            return {                ...toRefs(data),                ref__box,                ref__wrap,                ref__barX,                ref__barY,                handleMouseEnter,                handleMouseLeave,                handleDragThumb,                handleClickTrack,                updated,                handleResize,                handleScroll,                scrollTo,            }        }    }</script>
<v3-scroll @scroll="handleScroll">	<p><img src="; style="height:250px;" /></p>	<p>这里是内容信息!这里是内容信息!这里是内容信息!这里是内容信息!这里是内容信息!</p></v3-scroll>setup() {	// 监听滚动事件	const handleScroll = (e) => {		data.scrollTop = e.target.scrollTop		// 判断滚动状态		if(e.target.scrollTop == 0) {			data.scrollStatus = '到达顶部'		} else if(e.target.scrollTop + e.target.offsetHeight >= e.target.scrollHeight) {			data.scrollStatus = '到达底部'		}else {			data.scrollStatus = '滚动中....'		}	}		// ...}

好了,基于vue3.0实现pc端模拟滚动条就分享到这里。感谢大家的阅读!

标签: #js自动滚动条