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


Posted in Javascript onSeptember 14, 2018

在使用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>

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

Javascript 相关文章推荐
JS关闭窗口或JS关闭页面的几种代码分享
Oct 25 Javascript
a标签的href与onclick事件的区别详解
Nov 12 Javascript
jQuery实现无限往下滚动效果代码
Apr 16 Javascript
javascript实现将数字转成千分位的方法小结【5种方式】
Dec 11 Javascript
js实现密码强度检验
Jan 15 Javascript
javascript 动态生成css代码的两种方法
Mar 17 Javascript
详解Vue.use自定义自己的全局组件
Jun 14 Javascript
微信小程序实现下拉菜单切换效果
Mar 30 Javascript
js贪心算法 钱币找零问题代码实例
Sep 11 Javascript
vue计算属性无法监听到数组内部变化的解决方案
Nov 06 Javascript
vue自定义标签和单页面多路由的实现代码
May 03 Javascript
Ant-design-vue Table组件customRow属性的使用说明
Oct 28 Javascript
node中的session的具体使用
Sep 14 #Javascript
vue3.0 CLI - 2.1 -  component 组件入门教程
Sep 14 #Javascript
vue3.0 CLI - 1 - npm 安装与初始化的入门教程
Sep 14 #Javascript
详解Vue CLI3配置解析之css.extract
Sep 14 #Javascript
vue-cli脚手架build目录下utils.js工具配置文件详解
Sep 14 #Javascript
vue3.0 CLI - 2.6 - 组件的复用入门教程
Sep 14 #Javascript
在vue项目中使用md5加密的方法
Sep 14 #Javascript
You might like
教你如何把一篇文章按要求分段
2006/10/09 PHP
将RTF格式的文件转成HTML并在网页中显示的代码
2006/10/09 PHP
随时给自己贴的图片加文字的php代码
2007/03/08 PHP
探讨fckeditor在Php中的配置详解
2013/06/08 PHP
php中filter_input函数用法分析
2014/11/15 PHP
yii中widget的用法
2014/12/03 PHP
PHP通过微信跳转的Code参数获取用户的openid(关键代码)
2016/07/06 PHP
Zend Framework入门教程之Zend_View组件用法示例
2016/12/09 PHP
php正则提取html图片(img)src地址与任意属性的方法
2017/02/08 PHP
PHP时间日期增减操作示例【date strtotime实现加一天、加一月等操作】
2018/12/21 PHP
详解PHP的抽象类和抽象方法以及接口总结
2019/03/15 PHP
用javascript实现页面打印的三种方法
2007/03/05 Javascript
checkbox 多选框 联动实现代码
2008/10/22 Javascript
jquery 弹出层注册页面等(asp.net后台)
2010/06/17 Javascript
window.location.reload()方法刷新页面弹出要再次显示该网页对话框
2013/04/24 Javascript
Javascript表格翻页效果的具体实现
2013/10/05 Javascript
Jquery 复选框取值兼容FF和IE8(测试有效)
2013/10/29 Javascript
jquery图形密码实现方法
2015/03/11 Javascript
JS检测移动端横竖屏的代码
2016/05/30 Javascript
vue组件挂载到全局方法的示例代码
2018/08/02 Javascript
vue-test-utils初使用详解
2019/05/23 Javascript
vue项目出现页面空白的解决方案
2019/10/31 Javascript
Python中的两个内置模块介绍
2015/04/05 Python
Python实现豆瓣图片下载的方法
2015/05/25 Python
浅谈Python批处理文件夹中的txt文件
2019/03/11 Python
python 判断三个数字中的最大值实例代码
2019/07/24 Python
使用Python给头像戴上圣诞帽的图像操作过程解析
2019/09/20 Python
浅谈python中频繁的print到底能浪费多长时间
2020/02/21 Python
Django Auth用户认证组件实现代码
2020/10/13 Python
UNIX文件系统常用命令
2012/05/25 面试题
通信工程专业毕业生推荐信
2013/12/25 职场文书
群众路线对照检查材料
2014/09/22 职场文书
故宫的导游词
2015/01/31 职场文书
2015应届毕业生求职信范文
2015/03/20 职场文书
罗马假日观后感
2015/06/08 职场文书
《夸父追日》教学反思
2016/02/20 职场文书