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 相关文章推荐
javascript数组的扩展实现代码集合
Jun 01 Javascript
js解析与序列化json数据(三)json的解析探讨
Feb 01 Javascript
删除select中所有option选项jquery代码
Aug 12 Javascript
将input file的选择的文件清空的两种解决方案
Oct 21 Javascript
jquery结合CSS使用validate实现漂亮的验证
Jan 29 Javascript
jQuery实现Div拖动+键盘控制综合效果的方法
Mar 10 Javascript
javascript实现图片上传前台页面
Aug 18 Javascript
JavaScript关联数组用法分析【概念、定义、遍历】
Mar 15 Javascript
详解angular 中的自定义指令之详解API
Jun 20 Javascript
VUE 实现滚动监听 导航栏置顶的方法
Sep 11 Javascript
node.js的Express服务器基本使用教程
Jan 09 Javascript
Vue鼠标滚轮滚动切换路由效果的实现方法
Aug 04 Vue.js
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
php将session放入memcached的设置方法
2014/02/14 PHP
JS+PHP实现用户输入数字后显示最大的值及所在位置
2017/06/19 PHP
Laravel框架实现抢红包功能示例
2019/10/31 PHP
关于 byval 与 byref 的区别分析总结
2007/10/08 Javascript
JavaScript将相对地址转换为绝对地址示例代码
2013/07/19 Javascript
JavaScript中的运算符种类及其规则介绍
2013/09/26 Javascript
动态的绑定事件addEventListener方法的使用
2014/01/24 Javascript
js全选实现和判断是否有复选框选中的方法
2015/02/17 Javascript
JavaScript 实现的 zip 压缩和解压缩工具包Zip.js使用详解
2015/12/14 Javascript
jQuery在ie6下无法设置select选中的解决方法详解
2016/09/20 Javascript
javascript简易画板开发
2020/04/12 Javascript
JS中实现函数return多个返回值的实例
2017/02/21 Javascript
JS动态修改网页body的背景色实例代码
2017/10/07 Javascript
详解在WebStorm中添加Vue.js单文件组件的高亮及语法支持
2017/10/21 Javascript
nodejs中密码加密处理操作详解
2018/03/20 NodeJs
Vue不能检测到Object/Array更新的情况的解决
2018/06/26 Javascript
layui 优化button按钮和弹出框的方法
2018/08/15 Javascript
jQuery实现的别踩白块小游戏完整示例
2019/01/07 jQuery
Python删除指定目录下过期文件的2个脚本分享
2014/04/10 Python
python创建线程示例
2014/05/06 Python
Python THREADING模块中的JOIN()方法深入理解
2015/02/18 Python
Python EOL while scanning string literal问题解决方法
2020/09/18 Python
详解PyCharm配置Anaconda的艰难心路历程
2018/08/13 Python
利用Python实现微信找房机器人实例教程
2019/03/10 Python
Python使用统计函数绘制简单图形实例代码
2019/05/15 Python
Python paramiko模块使用解析(实现ssh)
2019/08/30 Python
使用Pandas的Series方法绘制图像教程
2019/12/04 Python
Python参数传递实现过程及原理详解
2020/05/14 Python
Matplotlib中%matplotlib inline如何使用
2020/07/28 Python
百度JavaScript笔试题
2015/01/15 面试题
自我鉴定范文
2013/11/10 职场文书
生产部统计员岗位职责
2014/01/05 职场文书
高中校园广播稿
2014/01/11 职场文书
ktv总经理岗位职责
2014/02/17 职场文书
法制宣传月活动方案
2014/05/11 职场文书
机关干部四风问题自我剖析及整改措施
2014/10/26 职场文书