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 相关文章推荐
jQuery1.6 使用方法二
Nov 23 Javascript
JavaScript在多浏览器下for循环的使用方法
Nov 07 Javascript
JS页面延迟执行一些方法(整理)
Nov 11 Javascript
jQuery中的val()示例应用
Feb 26 Javascript
jQuery使用hide方法隐藏页面上指定元素的方法
Mar 30 Javascript
JQuery中DOM加载与事件执行实例分析
Jun 13 Javascript
jQuery实现自动与手动切换的滚动新闻特效代码分享
Aug 27 Javascript
JavaScript数据结构与算法之链表
Jan 29 Javascript
js轮播图代码分享
Jul 14 Javascript
深入理解Javascript箭头函数中的this
Feb 13 Javascript
微信小程序实现简单评论功能
Nov 28 Javascript
Vue中使用JsonView来展示Json树的实例代码
Nov 16 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
php实现约瑟夫问题的方法小结
2015/03/23 PHP
[原创]php实现 data url的图片生成与保存
2016/12/04 PHP
PHP实现的大文件切割与合并功能示例
2018/04/10 PHP
JavaScript Sort 表格排序
2009/10/31 Javascript
ASP.NET jQuery 实例5 (显示CheckBoxList成员选中的内容)
2012/01/13 Javascript
JQuery each打印JS对象的方法
2013/11/13 Javascript
Javascript异步编程模型Promise模式详细介绍
2014/05/08 Javascript
jQuery对指定元素中指定字符串进行替换的方法
2015/03/17 Javascript
JQuery自动触发事件的方法
2015/06/13 Javascript
理解JavaScript中worker事件api
2015/12/25 Javascript
jQuery过滤选择器经典应用
2016/08/18 Javascript
vue自定义指令实现v-tap插件
2016/11/03 Javascript
Javascript基础回顾之(二) js作用域
2017/01/31 Javascript
微信小程序 仿美团分类菜单 swiper分类菜单
2017/04/12 Javascript
js使用原型对象(prototype)需要注意的地方
2017/08/28 Javascript
vuex操作state对象的实例代码
2018/04/25 Javascript
js 函数性能比较方法
2020/08/24 Javascript
解决antd日期选择组件,添加value就无法点击下一年和下一月问题
2020/10/29 Javascript
html中创建并调用vue组件的几种方法汇总
2020/11/17 Javascript
用vite搭建vue3应用的实现方法
2021/02/22 Vue.js
vue-router懒加载的3种方式汇总
2021/02/28 Vue.js
[13:40]TI3青蛙君全程回顾 DOTA2我们为梦想再战
2013/09/13 DOTA
python进程类subprocess的一些操作方法例子
2014/11/22 Python
解决Pycharm 包已经下载,但是运行代码提示找不到模块的问题
2019/08/31 Python
基于python全局设置id 自动化测试元素定位过程解析
2019/09/04 Python
Python序列对象与String类型内置方法详解
2019/10/22 Python
解决django无法访问本地static文件(js,css,img)网页里js,cs都加载不了
2020/04/07 Python
python解决OpenCV在读取显示图片的时候闪退的问题
2021/02/23 Python
HTML5 本地存储实现购物车功能
2017/09/07 HTML / CSS
玩具反斗城葡萄牙官方商城:Toys"R"Us葡萄牙
2016/10/21 全球购物
雅诗兰黛(Estee Lauder)英国官方网站:世界顶级化妆品牌
2016/12/29 全球购物
求职自荐信格式
2013/12/04 职场文书
2014学校庆三八妇女节活动总结
2014/03/01 职场文书
大学毕业生个人自荐书
2014/07/02 职场文书
雨雪天气温馨提示
2015/07/15 职场文书
浅谈Python魔法方法
2021/06/28 Java/Android