perfect-scrollbar 使用方法及注意事项

3,646 阅读5分钟

perfect-scrollbar 是极简但完_的(对于我们,也许对于大多数开发人员)滚动条插件。

  • 设计布局没有变化
  • 没有对 DOM 树的操作
  • 使用普通scrollTop和scrollLeft
  • 滚动条样式是完全可定制的
  • 布局更改的有效更新

github.com/mdbootstrap…

前言

官网:github.com/mdbootstrap…

 对于前端开发人员,在编写页面时总是会遇到添加滚动条的需求,但是浏览器自带的滚动条样式又过于......嗯,所以我们就会自己手动修改它的样式,手动修改随之而来的就是各种浏览器不兼容的问题,整的你一个头两个大,没错,我就被坑过。所以此刻我们无比需要一个能兼容所有浏览器又能修改样式的工具,它就是我们的完美滚动条(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 里面引入

error

  •  组件中使用

  组件中引入:

error

   给滚动条的区域添加 id :

error

   滚动条的父元素添加下面样式:

error

  一定要注意添加滚动条的区域要添加

error

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;

更多示例参考

github.com/mdbootstrap…

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