欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页  >  IT编程

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

程序员文章站 2022-07-22 16:53:18
在使用vue + element-ui 搭建后台管理页面的时候,做了一个头部、侧栏、面包屑固定的布局,导航栏和主要内容区域当内容超出时自动滚动。 使用的原因: 原来...

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

使用的原因:

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

.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 中表示不会写在文档中,需要用的自己看源码进行调用。

最终实现效果

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

实现步骤

一、阅读源码

通过阅读源码,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>

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