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 相关文章推荐
关于可运行代码无法正常执行的使用说明
May 13 Javascript
js 处理URL实用技巧
Nov 23 Javascript
什么是DOM(Document Object Model)文档对象模型
Mar 05 Javascript
jQuery点击弹出下拉菜单的小例子
Aug 01 Javascript
jQuery EasyUi实战教程之布局篇
Jan 26 Javascript
Jquery ui datepicker设置日期范围,如只能隔3天【实现代码】
May 04 Javascript
Async Validator 异步验证使用说明
Jul 03 Javascript
基于jQuery对象和DOM对象和字符串之间的转化实例
Aug 08 jQuery
Vue 动态设置路由参数的案例分析
Apr 24 Javascript
详解使用vue-admin-template的优化历程
May 20 Javascript
JS动态显示倒计时效果
Dec 12 Javascript
JavaScript实现单点登录的示例
Sep 23 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
使用Composer安装Yii框架的方法
2016/03/15 PHP
tp5(thinkPHP5框架)captcha验证码配置及验证操作示例
2019/05/28 PHP
深入理解JavaScript系列(10) JavaScript核心(晋级高手必读篇)
2012/01/15 Javascript
jQuery事件 delegate()使用方法介绍
2012/10/30 Javascript
js iframe跨域访问(同主域/非同主域)分别深入介绍
2013/01/24 Javascript
Javascript控制页面链接在新窗口打开具体方法
2013/08/16 Javascript
js自动生成的元素与页面原有元素发生堆叠的解决方法
2013/10/24 Javascript
SeaJS入门教程系列之完整示例(三)
2014/03/03 Javascript
js调试系列 初识控制台
2014/06/18 Javascript
基于jquery实现发送文章到手机的代码
2014/12/26 Javascript
JavaScript学习笔记之Function对象
2015/01/22 Javascript
自定义百度分享的分享按钮
2015/03/18 Javascript
js实现简单的可切换选项卡效果
2015/04/10 Javascript
Jquery中基本选择器用法实例详解
2015/05/18 Javascript
javascript入门之window对象【新手必看】
2016/11/22 Javascript
浅谈jquery的html方法里包含特殊字符的处理
2016/11/30 Javascript
js实现把图片的绝对路径转为base64字符串、blob对象再上传
2016/12/29 Javascript
vue-lazyload图片延迟加载插件的实例讲解
2018/02/09 Javascript
vue图片上传组件使用详解
2019/12/23 Javascript
python定时检查启动某个exe程序适合检测exe是否挂了
2013/01/21 Python
python实现给字典添加条目的方法
2014/09/25 Python
澳大利亚优惠网站:Deals.com.au
2019/07/02 全球购物
广州足迹信息技术有限公司Java软件工程师试题
2014/02/15 面试题
生产部主管岗位职责
2014/01/06 职场文书
国家励志奖学金个人先进事迹材料
2014/05/04 职场文书
庆国庆活动总结
2014/08/28 职场文书
2014教师党员个人自我评议
2014/09/20 职场文书
党员群众路线教育实践活动剖析材料
2014/10/10 职场文书
小学科学课教学反思
2016/02/23 职场文书
《当代神农氏》教学反思
2016/02/23 职场文书
员工给公司的建议书
2019/06/24 职场文书
SQL Server连接查询的实用教程
2021/04/07 SQL Server
apache基于端口创建虚拟主机的示例
2021/04/24 Servers
python 爬取华为应用市场评论
2021/05/29 Python
JavaScript分页组件使用方法详解
2021/07/26 Javascript
Java实现带图形界面的聊天程序
2022/06/10 Java/Android