(方法)基于 vue 自定义滚动条组件

个人项目地址: SubTopH前端开发个人站

(自己开发的前端功能和UI组件,一些有趣的小功能,感兴趣的伙伴可以访问,欢迎提出更好的想法,私信沟通,网站属于静态页面)

SubTopH前端开发个人站icon-default.png?t=N7T8https://subtop.gitee.io/subtoph.github.io/#/home

以上 👆 是个人前端项目,欢迎提出您的建议😊

以下是正文内容...............

 创建 vue 文件

  • 创建组件文件 scrollContainer.vue
<template>
  <div class="scrollbar-box" :style="{ height: height }">
    <div class="scrollbar-y">
      <div ref="scrollRef" class="scroll-wrap" @scroll="onMosewheel">
        <slot></slot>
      </div>
      <div v-show="heightPre < 1" ref="barRef" class="scrollbar-track">
        <div
          :style="{
            height: barHeight + 'px',
            transform: 'translateY(' + translateY + 'px)',
          }"
          class="scrollbar-thumb"
          @mousedown.stop.prevent="moveStart"
        ></div>
      </div>
    </div>
  </div>
</template>

<script>
export default {
  components: {},
  props: {
    height: {
      type: String,
      default: "100%",
    },
  },
  data() {
    return {
      isMove: false,
      trackHeight: 0, // 滚动条轨道高度
      wrapHeight: 0, // 容器高度(可视高度)
      wrapContentHeight: 0, // 内容高度(可滚动内容的高度)
      translateY: 0,
      moveClientY: 0,
      scrollTop: 0,
    };
  },
  computed: {
    barHeight() {
      return this.heightPre * this.trackHeight;
    },
    // 可视高度与内容高度的比例
    heightPre() {
      return this.wrapHeight / this.wrapContentHeight;
    },
  },
  watch: {},
  // 生命周期 - 创建完成(可以访问当前this实例)
  created() {},
  // 生命周期 - 挂载完成(可以访问DOM元素)
  mounted() {
    this.initScrollListner();
  },
  activated() {},
  methods: {
    initScrollListner(e) {
      const scroll = this.$refs.scrollRef;
      const bar = this.$refs.barRef;
      this.wrapContentHeight = scroll.scrollHeight;
      this.wrapHeight = scroll.clientHeight;
      this.trackHeight = bar.clientHeight;
    },
    updateScroll() {
      this.initScrollListner();
    },
    onMosewheel(e) {
      this.scrollY(e.target.scrollTop * this.heightPre);
    },
    scrollY(y) {
      this.translateY = y;
    },
    // 鼠标开始移动
    moveStart(e) {
      this.isMove = true;
      // 开始移动时鼠标距离thumb顶部的位置
      this.moveClientY = e.clientY - this.translateY;
      this.moveTo();
      this.moveEnd();
    },
    // 鼠标移动,改变thumb的位置以及容器scrollTop的位置
    moveTo() {
      document.onmousemove = (e) => {
        if (this.isMove) {
          if (
            e.clientY - this.moveClientY >
            this.trackHeight - this.barHeight
          ) {
            this.translateY = this.trackHeight - this.barHeight;
          } else if (e.clientY - this.moveClientY < 0) {
            this.translateY = 0;
          } else {
            this.translateY = e.clientY - this.moveClientY;
          }
          this.$refs.scrollRef.scrollTop = this.translateY / this.heightPre;
        }
      };
    },
    // 鼠标移动结束
    moveEnd() {
      document.onmouseup = (e) => {
        if (this.isMove) {
          this.isMove = false;
        }
      };
    },
  },
};
</script>
<style lang="less" scoped>
.scrollbar-box {
  height: 600px;
  overflow: hidden;
}
.scrollbar-y {
  position: relative;
  height: 100%;
  margin-right: -17px;
  .scroll-wrap {
    height: 100%;
    overflow-y: scroll;
  }
  .scrollbar-track {
    position: absolute;
    top: 0;
    right: 17px;
    bottom: 0;
    width: 16px;
    background-color: #000000; //背景
    border-radius: 8px;
    z-index: 20;
    .scrollbar-thumb {
      width: 12px;
      margin: 0 auto;
      height: 20%;
      background-color: #eeeeee; //滑块
      border-radius: 6px;
      cursor: default;
      // transition: all 0.01s;
    }
  }
}
</style>
  • 组件内引入注册使用
<template>
  <!-- 组件列表展示 -->
  <div class="content">
    <!-- 滚动条盒子 -->
    <div id="scrollContainer" class="layout">
      <p class="tit">自定义滚动条(scrollContainer)</p>
      <div class="layout-box">
        <scrollContainer
          ref="scrollbarRef"
          height="100%"
          class="scroll-container"
        >
          <ul v-for="item in 17" :key="item">
            <li>{{ item }} 信息列表</li>
          </ul>
        </scrollContainer>
      </div>
    </div>
  </div>
</template>
<script>
//引入封装滚动条组件
import ScrollbarContainer from '@/components/scrollbar/index.vue'
export default {
  components: {
    //注册组件
    ScrollbarContainer
  },
  mounted() {
    // *注:demo更新需要更新容器
    this.$nextTick(() => {
      this.$refs.scrollbarRef.updateScroll()
    })
  }
}
</script>
<style lang="less" scoped>
.layout {
  padding: 20px;
  width: 90%;
  margin: 0 auto;
  margin-top: 30px;
  box-sizing: border-box;
  .tit {
    margin: 10px 0;
    box-sizing: border-box;
    font-size: 20px;
    font-weight: 700px;
  }
}
// 滚动条盒子
.layout-box {
  border: 1px solid #ddd;
  margin: 0 auto;
  height: 200px;
}
</style>
  • 全局注册使用
// index.js引入注册组件
import ScrollbarContainer from "./scrollContainer.vue";
function plugins(Vue) {
  Vue.component("ScrollbarContainer", ScrollbarContainer);
}
export default plugins;
// main.js全局引入组件,组件中直接标签使用即可
import Vue from 'vue'
import App from './App.vue'
import router from './router'
import store from './store'
Vue.config.productionTip = false
// 引入组件
import plugins from './components/index'
// 注册组件
Vue.use(plugins);
new Vue({
  router,
  store,
  render: h => h(App)
}).$mount('#app')

  • 1
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值