Element-ui之ElScrollBar组件滚动条的使用方法

在使用vue + element-ui 搭建后台管理页面的时候,做了一个头部、侧栏、面包屑固定的布局,导航栏和主要内容区域当内容超出时自动滚动。

使用的原因:

原来是采用优化浏览器样式的方式,对滚动条进行样式调整。但这个方法并不兼容火狐浏览器,在火狐访问时依然是浏览器认的滚动条样式。

rush:css;"> .sidebar { position: fixed; border-right: 1px solid rgba(0,.07); overflow-y: auto; position: absolute; top: 0; bottom: 0; left: 0; transition: transform .25s ease-out; width: 300px; z-index: 3; } .sidebar::-webkit-scrollbar { width: 4px }

.sidebar::-webkit-scrollbar-thumb {
background: transparent;
border-radius: 4px
}

.sidebar:hover::-webkit-scrollbar-thumb {
background: hsla(0,0%,53%,.4)
}

.sidebar:hover::-webkit-scrollbar-track {
background: hsla(0,.1)
}

灵感来源

在翻看 element-ui官网的文档时,发现其左侧导航和右边的内容超出屏幕时,滚动条的样式比较小巧,通过浏览器审查工具查看,发现它是使用了el-scrollbar的样式,跟element-ui的组件样式命名一致。但文档中并没有关于这个 scrollbar组件的使用文档,搜索一番得知这是一个隐藏组件,官方在 github 的 issues 中表示不会写在文档中,需要用的自己看源码进行调用

最终实现效果

实现步骤

一、阅读源码

通过阅读源码,scrollbar组件暴露了 native,wrapStyle,wrapClass,viewClass,viewStyle,noresize,tag 这7个 props属性

rush:js;"> props: { native: Boolean,// 是否使用本地,设为true则不会启用element-ui自定义的滚动条 wrapStyle: {},// 包裹层自定义样式 wrapClass: {},// 包裹层自定义样式类 viewClass: {},// 可滚动部分自定义样式类 viewStyle: {},// 可滚动部分自定义样式 noresize: Boolean,// 如果 container 尺寸不会发生变化,最好设置它可以优化性能 tag: { // 生成标签类型,认使用 `div`标签包裹 type: String,default: 'div' } }

二、在页面中使用 el-scrollbar组件

rush:js;">

以上代码就是对 el-scrollbar 的使用了,属性不需要用的就不用写。

源码

源码在node_modules 目录下的 element-ui/packages/scrollbar

模块入口index.js,从main导入 scrollbar并提供一个安装方法注册成全局组件

rush:js;"> import Scrollbar from './src/main';

/ istanbul ignore next /
Scrollbar.install = function(Vue) {
Vue.component(Scrollbar.name,Scrollbar);
};

export default Scrollbar;

src/main.js 源码

rush:js;"> // reference https://github.com/noeldelgado/gemini-scrollbar/blob/master/index.js

import { addResizeListener,removeResizeListener } from 'element-ui/src/utils/resize-event';
import scrollbarWidth from 'element-ui/src/utils/scrollbar-width';
import { toObject } from 'element-ui/src/utils/util';
import Bar from './bar';

/ istanbul ignore next /
export default {
name: 'ElScrollbar',components: { Bar },props: {
native: Boolean,wrapStyle: {},wrapClass: {},viewClass: {},viewStyle: {},noresize: Boolean,// 如果 container 尺寸不会发生变化,最好设置它可以优化性能
tag: {
type: String,default: 'div'
}
},data() {
return {
sizeWidth: '0',sizeHeight: '0',moveX: 0,moveY: 0
};
},computed: {
wrap() {
return this.$refs.wrap;
}
},render(h) {
let gutter = scrollbarWidth();
let style = this.wrapStyle;

if (gutter) {
const gutterWith = -${gutter}px;
const gutterStyle = margin-b<a href="https://www.jb51.cc/tag/ott/" target="_blank" class="keywords">ott</a>om: ${gutterWith}; margin-right: ${gutterWith};;

if (Array.isArray(this.wrapStyle)) {
style = toObject(this.wrapStyle);
style.marginRight = style.marginBottom = gutterWith;
} else if (typeof this.wrapStyle === 'string') {
style += gutterStyle;
} else {
style = gutterStyle;
}
}
const view = h(this.tag,{
class: ['el-scrollbarview',this.viewClass],style: this.viewStyle,ref: 'resize'
},this.$slots.default);
const wrap = (
<div
ref="wrap"
style={ style }
onScroll={ this.handleScroll }
class={ [this.wrapClass,'el-scrollbar
wrap',gutter ? '' : 'el-scrollbar__wrap--hidden-default'] }>
{ [view] }

); let nodes;

if (!this.native) {
nodes = ([
wrap,<Bar
move={ this.moveX }
size={ this.sizeWidth }>,<Bar
vertical
move={ this.moveY }
size={ this.sizeHeight }>
]);
} else {
nodes = ([
<div
ref="wrap"
class={ [this.wrapClass,'el-scrollbar__wrap'] }
style={ style }>
{ [view] }

]); } return h('div',{ class: 'el-scrollbar' },nodes); },methods: { handleScroll() { const wrap = this.wrap;

this.moveY = ((wrap.scrollTop 100) / wrap.clientHeight);
this.moveX = ((wrap.scrollLeft
100) / wrap.clientWidth);
},update() {
let heightPercentage,widthPercentage;
const wrap = this.wrap;
if (!wrap) return;

heightPercentage = (wrap.clientHeight 100 / wrap.scrollHeight);
widthPercentage = (wrap.clientWidth
100 / wrap.scrollWidth);

this.sizeHeight = (heightPercentage < 100) ? (heightPercentage + '%') : '';
this.sizeWidth = (widthPercentage < 100) ? (widthPercentage + '%') : '';
}
},mounted() {
if (this.native) return;
this.$nextTick(this.update);
!this.noresize && addResizeListener(this.$refs.resize,this.update);
},beforeDestroy() {
if (this.native) return;
!this.noresize && removeResizeListener(this.$refs.resize,this.update);
}
};

示例

rush:xhtml;">

以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持编程之家。

相关文章

前言 做过web项目开发的人对layer弹层组件肯定不陌生,作为l...
前言 前端表单校验是过滤无效数据、假数据、有毒数据的第一步...
前言 图片上传是web项目常见的需求,我基于之前的博客的代码...
前言 导出Excel文件这个功能,通常都是在后端实现返回前端一...
前言 众所周知,js是单线程的,从上往下,从左往右依次执行,...
前言 项目开发中,我们可能会碰到这样的需求:select标签,禁...