视频1 视频21 视频41 视频61 视频文章1 视频文章21 视频文章41 视频文章61 推荐1 推荐3 推荐5 推荐7 推荐9 推荐11 推荐13 推荐15 推荐17 推荐19 推荐21 推荐23 推荐25 推荐27 推荐29 推荐31 推荐33 推荐35 推荐37 推荐39 推荐41 推荐43 推荐45 推荐47 推荐49 关键词1 关键词101 关键词201 关键词301 关键词401 关键词501 关键词601 关键词701 关键词801 关键词901 关键词1001 关键词1101 关键词1201 关键词1301 关键词1401 关键词1501 关键词1601 关键词1701 关键词1801 关键词1901 视频扩展1 视频扩展6 视频扩展11 视频扩展16 文章1 文章201 文章401 文章601 文章801 文章1001 资讯1 资讯501 资讯1001 资讯1501 标签1 标签501 标签1001 关键词1 关键词501 关键词1001 关键词1501 专题2001
Element-ui之ElScrollBar组件滚动条的使用方法
2020-11-27 22:07:44 责编:小采
文档
.sidebar {
 position: fixed;
 border-right: 1px solid rgba(0,0,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,0%,53%,.1)
}

灵感来源

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

最终实现效果

实现步骤

一、阅读源码

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

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

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

<template>
 <div>
 <el-scrollbar :native="false" wrapStyle="" wrapClass="" viewClass="" viewStyle="" noresize="false" tag="section">
 <div>
 <p v-for="(item, index) in 200" :key="index">{{index}} 这里是一些文本。</p>
 </div>
 <el-scrollbar>
 </div>
</template>

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

源码

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

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

import Scrollbar from './src/main';

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

export default Scrollbar;

src/main.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-bottom: ${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-scrollbar__view', 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] }
 </div>
 );
 let nodes;

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

示例

<div style="height: 100vh;">
 <!-- 注意需要给 el-scrollbar 设置高度,判断是否滚动是看它的height判断的 -->
 <el-scrollbar style="height: 100%;"> <!-- 滚动条 -->
 <div style="height: 500px;width: 100%;background: red;"></div>
 <div style="height: 500px;width: 100%;background: yellowgreen;"></div>
 <div style="height: 500px;width: 100%;background: blueviolet;"></div>
 </el-scrollbar><!-- /滚动条 -->
</div>

下载本文
显示全文
专题