目录
1、缘起
2、实际示例
3、美化滚动条
4、Element-plus中的滚动条
5、关于实现方式的思考
1、缘起
之前在做项目时,发现一个项目中,各个子应用项目的UI表现不一致,看了下式Vue项目滚动条和其他的子应用项目表现明显不一致。
有时候为了使界面滚动条,各个浏览器的滚动条能保持一致,这样我们的项目避免在各个浏览器存在差异导致UI界面的不一致,这时候我们就可以考虑使用通用组件的方式,对各个需要滚动的页面,或者弹出窗口添加统一的组件进行包裹,来保证滚动效果在各个浏览器中能有更好的体验效果。
2、实际示例
我们以element-ui官网为例,看下默认滚动条实际效果。
在firefox 浏览器中,如下所示:
在Chrome 浏览器中,如下所示:
在Edge浏览器中,如下所示:
在以上各个浏览器中展示的效果来说,默认滚动条在各个浏览器中的表现都不一致,firefox浏览器和chrome浏览器相差就比较小,而与Edge浏览器相比相差就比较大了。
我们以element-ui官网为例,看下添加通用组件之后,滚动条实际效果。
在firefox 浏览器中,如下所示:
在chrome浏览器中,如下所示:
在Edge浏览器中,如下所示:
最后我们看到各个浏览器中滚动条的效果,基本上各个浏览器的表现效果是一致的,添加通用组件,默认情况下滚动条是不显示的,只有鼠标移动过去才会进行显示,整体上效果和用户体验会更好。
3、美化滚动条
我们打开这个网址(Create a New Pen (codepen.io))进行示例代码的编写。
我们对HTML 稍微改变以下,看下Dialog。
<script src="//unpkg.com/vue@2/dist/vue.js"></script>
<script src="//unpkg.com/element-ui@2.15.13/lib/index.js"></script>
<div id="app">
<el-button type="text" @click="dialogVisible = true">点击打开 Dialog</el-button>
<el-dialog title="提示" :visible.sync="dialogVisible" width="30%" :before-close="handleClose">
<el-scrollbar class="test">
<div>这是一段信息</div>
<div>这是一段信息</div>
<div>这是一段信息</div>
<div>这是一段信息</div>
<div>这是一段信息</div>
<div>这是一段信息</div>
<div>这是一段信息</div>
<div>这是一段信息</div>
</el-scrollbar>
<span slot="footer" class="dialog-footer">
<el-button @click="dialogVisible = false">取 消</el-button>
<el-button type="primary" @click="dialogVisible = false">确 定</el-button>
</span>
</el-dialog>
</div>
<style>
.test {
height: 100px;
}
.el-scrollbar__wrap{
overflow-x: hidden;
}
</style>
我们看下效果:
我们可以看到垂直滚动条的样式已经发生变化了,我们引用了element-ui的组件<el-scrollbar></el-scrollbar>这个组件对超过高度的内容进行了包裹。
在element-ui(2.xx.xx)官网上,并没有找到有这个组件,实际上是有的,没有给出对应组件对应的文档,可能组件在设计的时候没有更好的完善吧。下载对应源码,看到是有这个组件的。
打开对应主文件,传递的属性有几个:
props: {
native: Boolean, // 是否使用原生方式
wrapStyle: {}, // 包裹容器的自定义样式
wrapClass: {}, // 包裹容器的自定义类名
viewClass: {}, // 视图的自定义样式
viewStyle: {}, // 视图的自定义类名
noresize: Boolean, // 如果 container 尺寸不会发生变化,最好设置它可以优化性能
tag: { // 视图的元素标签,默认为 div 标签
type: String,
default: 'div'
}
},
在源码顶部,看到有一个链接地址,是参考另一个插件的实现,如下所示
// reference https://github.com/noeldelgado/gemini-scrollbar/blob/master/index.js
打开它对应的网站(https://noeldelgado.github.io/gemini-scrollbar/),我们可以看到官网本身也进行了对应实现。
开发chrome开发工具,在元素标签页中,我们可以看到通过自定义节点,然后给节点添加对应的事件去进行实现的。
4、Element-plus中的滚动条
我们Element-plus 的官网,发现有滚动条组件对应的说明文档,如下所示:
通过文档给定的属性,发现和element-ui中的滚动条类型,只不过增加了宽、高等部分属性,使用起来和element-ui的滚动条没什么太大区别。
我们看一下如下示例:
<template>
<el-scrollbar height="400px">
<p v-for="item in 20" :key="item" class="scrollbar-demo-item">{{ item }}</p>
</el-scrollbar>
</template>
<style scoped>
.scrollbar-demo-item {
display: flex;
align-items: center;
justify-content: center;
height: 50px;
margin: 10px;
text-align: center;
border-radius: 4px;
background: var(--el-color-primary-light-9);
color: var(--el-color-primary);
}
</style>
效果如下所示:
5、关于实现方式的思考
首先,我们检查滚动条的大小, 如果滚动条大小等于零(这意味着当前区域不需要滚动条) 那么我们什么都不做,否则我们“隐藏”本机滚动条(保留其功能 完整),并创建一对新的“滚动条”,由div组成,您可以完全自定义 用CSS这些“滚动条”将更新其位置,而 滚动以获得视觉反馈,如果您单击或拖动它们,也会做出响应。
例如,我们可以创建如下节点添加到html中。
.scrollbar-measure {
width: 100px;
height: 100px;
overflow: scroll;
position: absolute;
top: -9999px;
}
滚动条宽度,我们可以动态进行计算。
// Create the measurement nodevar scrollDiv = document.createElement("div");
scrollDiv.className = "scrollbar-measure";
document.body.appendChild(scrollDiv);
// Get the scrollbar widthvar scrollbarWidth = scrollDiv.offsetWidth - scrollDiv.clientWidth;
console.warn(scrollbarWidth); // Mac: 15
// Delete the DIV
document.body.removeChild(scrollDiv);
使用页面中的元素,从clientWidth中减去offsetWidth即可得到滚动条的大小! 最后一步是从DOM中删除DIV,完成了!
实际上很多其他组件的实现,基本上都是基于这样的方式去进行实现的。