perfect-scrollbar 是极简但完_的(对于我们,也许对于大多数开发人员)滚动条插件。
- 设计布局没有变化
- 没有对 DOM 树的操作
- 使用普通scrollTop和scrollLeft
- 滚动条样式是完全可定制的
- 布局更改的有效更新
前言
对于前端开发人员,在编写页面时总是会遇到添加滚动条的需求,但是浏览器自带的滚动条样式又过于......嗯,所以我们就会自己手动修改它的样式,手动修改随之而来的就是各种浏览器不兼容的问题,整的你一个头两个大,没错,我就被坑过。所以此刻我们无比需要一个能兼容所有浏览器又能修改样式的工具,它就是我们的完美滚动条(perfect-scrollbar)。
perfect-scrollbar 是极简但_完美_的(对于我们,也许对于大多数开发人员)滚动条插件。
- 设计布局没有变化
- 没有对 DOM 树的操作
- 使用普通 scrollTop和 scrollLeft
- 滚动条样式是完全可定制的
- 布局更改的有效更新
注意
除非不得不使用自定义滚动条,否则始终建议使用浏览器自带的滚动条。
支持chrome、IE11、edge、火狐等浏览器,其中IE11中的scrollbar在使用时会有一点渲染问题,缺点是不支持IE10以下的IE和edge
使用
接下来我们来看看它在 vue 中的使用
- 下载安装 npm install perfect-scrollbar
npm install perfect-scrollbar
下载成功后你的 package.json 里面就会此依赖
- 配置
在你的 main.js 里面引入
- 组件中使用
组件中引入:
给滚动条的区域添加 id :
滚动条的父元素添加下面样式:
一定要注意添加滚动条的区域要添加:
js 部分需要及时销毁:
let projectListDOM = null;
let projectListPs = null;
onMounted(()=>{
projectListDOM = document.querySelector('#project_body_scroll .ant-table-body');
projectListPs = new PerfectScrollbar(projectListDOM);
});
onBeforeUnmount(()=>{
if (projectListPs) {
projectListPs.destroy();
projectListPs = null;
}
projectListDOM = null;
});
快速上手
初始化:
const container = document.querySelector('#container');
const ps = new PerfectScrollbar(container);
// or just with selector string
const ps = new PerfectScrollbar('#container');
可以使用option进行初始化。(推荐使用这种方式,因为这样可以更细致的设置,设置方法在下面)
const ps = new PerfectScrollbar('#container', {
wheelSpeed: 2,
wheelPropagation: true,
minScrollbarLength: 20
});
如果容器或内容的大小发生变化,请使用update进行更新。
ps.update();
如果要销毁滚动条,请使用destroy。
ps.destroy();
ps = null; // to make sure garbages are collected
如果您想滚动到某个地方,只需更新scrollTop。
const container = document.querySelector('#container');
container.scrollTop = 0;
更多示例参考
hook usePerfectScrollbar.js
封装
import PerfectScrollbar from 'perfect-scrollbar';
import 'perfect-scrollbar/css/perfect-scrollbar.css';
export default function usePerfectScrollbar() {
let ps = null;
const resize = () => {
ps && ps.update();
};
return {
install(el) {
if (el) {
ps = new PerfectScrollbar(el, {
wheelSpeed: 2,
wheelPropagation: false
});
window.addEventListener('resize', resize, false);
return ps;
}
},
uninstall() {
window.removeEventListener('resize', resize, false);
ps && ps.destroy();
}
};
}
指令 scrollbar.js
封装
import PerfectScrollbar from 'perfect-scrollbar';
import 'perfect-scrollbar/css/perfect-scrollbar.css';
const defaultOptions = {
maxScrollbarLength: 100
};
function installScrollBar(el, binding) {
if (!binding.value) {
el._ps = new PerfectScrollbar(el, {});
} else {
let className = '';
let options = defaultOptions;
const str = binding.value;
if (typeof str === 'string' && str.constructor === String) {
className = binding.value;
} else if (Object.prototype.toString.call(str) === '[object Object]') {
// eslint-disable-next-line prefer-destructuring
className = binding.value.className;
options = binding.value.options || defaultOptions;
}
if (className) {
const targetEl = el.querySelector(className);
if (targetEl) {
el._ps = new PerfectScrollbar(targetEl, options);
}
} else {
el._ps = new PerfectScrollbar(el, options);
}
}
}
/**
* 基于perfect-scrollbar 封装的滚动条指令
* 使用示例:v-scrollbar="{className:`.el-table__body-wrapper`}"
* v-scrollbar="`.el-table__body-wrapper`"
* v-scrollbar="`.vue-easy-tree`"
* 注意这里的 className 应该是滚动区域的class
* 指令写在滚动区域的父元素上
* 支持传入options
* @type {null}
*/
export default {
inserted(el, binding) {
installScrollBar(el, binding);
},
componentUpdated(el, binding) {
if (el._ps) {
setTimeout(() => {
el._ps && el._ps.update();
}, 500);
} else {
installScrollBar(el, binding);
}
},
unbind(el) {
el._ps && el._ps.destroy();
el._ps = null;
}
};
全局注册
import vScrollbar from '@/directives/scrollbar';
Vue.directive('scrollbar', vScrollbar);
注意事项
-
滚动区域的父元素的高度必须固定
-
滚动区域必须设置
position: relative;
- 父元素必须设置
overflow: hidden;
-
关于样式(颜色透明度等),可以通过设置.ps__rail-y等的css进行设置,注意加!important,
-
padding 应该添加在滚动区域的父元素,这样滚动条才不会遮挡内容
其他使用示例(API)
ps.update()
处理大小变化,执行更新操作
<!--Handle size change-->
<script>
// Initialize the plugin
const demo = document.querySelector('#container');
const ps = new PerfectScrollbar(demo);
// Handle size change
document.querySelector('#resize').addEventListener('click', () => {
// Get updated values
width = document.querySelector('#width').value;
height = document.querySelector('#height').value;
// Set demo sizes
demo.style.width = `${width}px`;
demo.style.height = `${height}px`;
// Update Perfect Scrollbar
ps.update();
});
</script>
ps.destroy()
销毁滚动条实例,注意需要先判空
<!--ADD / REMOVE PERFECT SCROLLBAR FROM CONTAINER-->
<script>
var $ = document.querySelector.bind(document);
var ps;
$('#init').addEventListener('click', () => {
if (ps) ps.destroy();
ps = new PerfectScrollbar('#container');
});
$('#remove').addEventListener('click', () => {
if (ps) ps.destroy();
ps = null;
});
</script>
add('ps--focus')
- 使用
setTimeout函数延迟了添加类名的操作,确保它在初始化 Perfect Scrollbar 后立即执行。 $('#container').classList.add('ps--focus')添加了一个名为ps--focus的类名,用于样式或其他目的,模拟容器被聚焦的效果。setTimeout(() => $('#container').classList.remove('ps--focus'), 750)在延迟后(750毫秒后)移除了添加的类名,为了模拟一个聚焦效果的短暂状态。
<!--ADD PERFECT SCROLLBAR TO CONTAINER-->
<script>
var $ = document.querySelector.bind(document);
new PerfectScrollbar('#container');
setTimeout(() => $('#container').classList.add('ps--focus'), 0);
setTimeout(() => $('#container').classList.remove('ps--focus'), 750);
</script>
options
(通过在option中设置以下属性可以更细致的设置scrollbar的样式)
handlers {String[]}
它是处理程序列表,用于滚动元素。(这里面是可以操作滚动条的方式)
默认:['click-rail', 'drag-thumb', 'keyboard', 'wheel', 'touch']
wheelSpeed {Number}
应用于鼠标滚轮事件的滚动速度。
默认:1
wheelPropagation {Boolean}
如果这个选项为true,当滚动到达底端,鼠标滚轮事件将被传给父元素。
默认:false
swipeEasing {Boolean}
如果此选项为true,将简化滑动滚动。
默认:true
minScrollbarLength {Number?}
设置为整数值时,滚动条的拇指部分(就是滚动条的高亮部分)不会缩小到该像素数以下(最小宽度)。
默认:null
maxScrollbarLength {Number?}
设置为整数值时,滚动条的拇指部分将不会扩展到该数量的像素。
默认:null
scrollingThreshold {Number}
这将设置阈值,ps--scrolling-x并ps--scrolling-y保留类别。在默认CSS中,无论悬停状态如何,它们都会显示滚动条。单位是毫秒。(scrollbar的响应时间)
默认:1000
useBothWheelAxes {Boolean}
设置为true时,只有一个(垂直或水平)滚动条可见,然后垂直和水平滚动都会影响该滚动条。
默认:false
suppressScrollX {Boolean}
设置为true时,无论内容宽度如何,X轴上的滚动条都将不可用。
默认:false
suppressScrollY {Boolean}
设置为true时,无论内容高度如何,Y轴上的滚动条都不可用。
默认:false
scrollXMarginOffset {Number}
在不启用X轴滚动条的情况下,内容宽度可以超过容器宽度的像素数。允许一些“摆动空间”或“偏移中断”,因此仅由于几个像素而不能启用X轴滚动条。
默认:0
scrollYMarginOffset {Number}
在不启用Y轴滚动条的情况下,内容高度可以超过容器高度的像素数。允许一些“摆动空间”或“偏移中断”,因此仅由于几个像素而不能启用Y轴滚动条。
默认:0