使用vue3实现简单的滑块组件

 更新时间:2023年08月01日 10:58:26   作者:bigFace  
这篇文章主要给大家介绍一下如何使用vue3实现简单的滑块组件,文中有详细的代码示例讲解,具有一定的参考价值,感兴趣的小伙伴跟着小编一起来看看吧

滑块组件主要是利用鼠标事件,让滑块跟着鼠标跟着x轴动,效果如下。

创建了一个名为 CustomSlider 的自定义滑块组件。它接受 minmax 和 step 作为 props,用于设置滑块的取值范围和步长。使用 emits 属性声明了一个名为 update:modelValue 的自定义事件,用于向父组件发送滑块值的更新。

name: 'CustomSlider',
props: { min: { type: Number, default: 0 }, 
    max: { type: Number, default: 100 }, 
    step: { type: Number, default: 1 } },
emits: ['update:modelValue'],

在 setup 函数中,我们使用了 Vue 3 的组合式 API 来定义滑块组件的逻辑。我们使用了 ref 来创建了 thumbPosition 和 isDragging 两个响应式变量。thumbPosition 用于控制滑块的位置,isDragging 用于标记是否正在拖动滑块。

通过计算属性 trackWidth,我们根据最小值和最大值计算出滑块轨道的宽度,用于动态设置样式。

   const thumbPosition = ref('0%');
    const isDragging = ref(false);
    const trackWidth = computed(() => {
      const range = props.max - props.min;
      return `${(100 * range) / (props.max - props.min)}%`;
    });

在 startDrag 方法中,我们监听了滑块的鼠标按下事件,并在按下时开始拖动操作。在 handleDrag 方法中,我们根据鼠标位置计算出滑块的值,并通过 emit 方法触发 update:modelValue 事件,将滑块的值发送给父组件。

 const startDrag = (event) => {
      isDragging.value = true;
      document.addEventListener('mousemove', handleDrag);
      document.addEventListener('mouseup', stopDrag);
    };
    const handleDrag = (event) => {
      if (isDragging.value) {
        const sliderWidth = event.target.parentNode.offsetWidth;
        const offsetX = event.pageX - event.target.parentNode.offsetLeft;
        const percentage = (offsetX / sliderWidth) * 100;
        const value = (percentage * (props.max - props.min)) / 100 + props.min;
        const snappedValue = Math.round(value / props.step) * props.step;
        const clampedValue = Math.max(props.min, Math.min(props.max, snappedValue));
        thumbPosition.value = `${((clampedValue - props.min) / (props.max - props.min)) * 100}%`;
        emit('update:modelValue', clampedValue);
      }
    };
    const stopDrag = () => {
      isDragging.value = false;
      document.removeEventListener('mousemove', handleDrag);
      document.removeEventListener('mouseup', stopDrag);
    };

在 onMounted 和 onUnmounted 钩子中,我们分别添加和移除了监听鼠标抬起事件的事件处理函数,以确保在组件销毁时正确清理事件监听器。

  onMounted(() => {
      document.addEventListener('mouseup', stopDrag);
    });
    onUnmounted(() => {
      document.removeEventListener('mouseup', stopDrag);
    });

完整代码如下:

<template>
  <div class="slider">
    <div class="track" :style="{ width: trackWidth }"></div>
    <div class="thumb" :style="{ left: thumbPosition }" @mousedown="startDrag"></div>
  </div>
</template>
<script>
import { ref, computed, onMounted, onUnmounted } from 'vue';
export default {
  name: 'CustomSlider',
  props: {
    min: {
      type: Number,
      default: 0
    },
    max: {
      type: Number,
      default: 100
    },
    step: {
      type: Number,
      default: 1
    }
  },
  emits: ['update:modelValue'],
  setup(props, { emit }) {
    const thumbPosition = ref('0%');
    const isDragging = ref(false);
    const trackWidth = computed(() => {
      const range = props.max - props.min;
      return `${(100 * range) / (props.max - props.min)}%`;
    });
    const startDrag = (event) => {
      isDragging.value = true;
      document.addEventListener('mousemove', handleDrag);
      document.addEventListener('mouseup', stopDrag);
    };
    const handleDrag = (event) => {
      if (isDragging.value) {
        const sliderWidth = event.target.parentNode.offsetWidth;
        const offsetX = event.pageX - event.target.parentNode.offsetLeft;
        const percentage = (offsetX / sliderWidth) * 100;
        const value = (percentage * (props.max - props.min)) / 100 + props.min;
        const snappedValue = Math.round(value / props.step) * props.step;
        const clampedValue = Math.max(props.min, Math.min(props.max, snappedValue));
        thumbPosition.value = `${((clampedValue - props.min) / (props.max - props.min)) * 100}%`;
        emit('update:modelValue', clampedValue);
      }
    };
    const stopDrag = () => {
      isDragging.value = false;
      document.removeEventListener('mousemove', handleDrag);
      document.removeEventListener('mouseup', stopDrag);
    };
    onMounted(() => {
      document.addEventListener('mouseup', stopDrag);
    });
    onUnmounted(() => {
      document.removeEventListener('mouseup', stopDrag);
    });
    return {
      thumbPosition,
      trackWidth,
      startDrag
    };
  }
};
</script>
<style>
.slider {
  position: relative;
  width: 100%;
  height: 10px;
  background-color: #ccc;
}
.track {
  position: absolute;
  top: 0;
  left: 0;
  height: 100%;
  background-color: #409eff;
}
.thumb {
  position: absolute;
  top: -5px;
  left: 0;
  width: 20px;
  height: 20px;
  border-radius: 50%;
  background-color: #409eff;
  cursor: pointer;
}
</style>

到此这篇关于使用vue3实现简单的滑块组件的文章就介绍到这了,更多相关vue3实现滑块组件内容请搜索脚本之家以前的文章或继续浏览下面的相关文章希望大家以后多多支持脚本之家!

相关文章

  • vue创建项目卡住不动,vue create project卡住不动的解决

    vue创建项目卡住不动,vue create project卡住不动的解决

    这篇文章主要介绍了vue创建项目卡住不动,vue create project卡住不动的解决方案,具有很好的参考价值,希望对大家有所帮助。如有错误或未考虑完全的地方,望不吝赐教
    2022-10-10
  • 一篇文章带你吃透Vue生命周期(结合案例通俗易懂)

    一篇文章带你吃透Vue生命周期(结合案例通俗易懂)

    这篇文章主要给大家介绍了关于如何通过一篇文章带你吃透Vue生命周期,文章通过结合案例更加的通俗易懂,对大家的学习或者工作具有一定的参考学习价值,需要的朋友可以参考下
    2022-02-02
  • vue生命周期beforeDestroy和destroyed调用方式

    vue生命周期beforeDestroy和destroyed调用方式

    这篇文章主要介绍了vue生命周期beforeDestroy和destroyed调用方式,具有很好的参考价值,希望对大家有所帮助。如有错误或未考虑完全的地方,望不吝赐教
    2022-06-06
  • 路由vue-route的使用示例教程

    路由vue-route的使用示例教程

    这篇文章主要介绍了路由vue-route的使用,本文结合示例代码给大家介绍的非常详细,对大家的学习或工作具有一定的参考借鉴价值,需要的朋友可以参考下
    2022-12-12
  • Vue与Node.js通过socket.io通信的示例代码

    Vue与Node.js通过socket.io通信的示例代码

    这篇文章主要介绍了Vue与Node.js通过socket.io通信的示例代码,小编觉得挺不错的,现在分享给大家,也给大家做个参考。一起跟随小编过来看看吧
    2018-07-07
  • Vue Element UI自定义描述列表组件

    Vue Element UI自定义描述列表组件

    这篇文章主要为大家详细介绍了Vue Element UI自定义描述列表组件,文中示例代码介绍的非常详细,具有一定的参考价值,感兴趣的小伙伴们可以参考一下
    2021-05-05
  • vue项目网页自适应等比例放大缩小实例代码

    vue项目网页自适应等比例放大缩小实例代码

    等比例缩放可以在不同的分辨率下都能够一屏展示,不会有滚动条的问题,也不会有适配问题,下面这篇文章主要给大家介绍了关于vue项目网页自适应等比例放大缩小的相关资料,需要的朋友可以参考下
    2022-11-11
  • proxy实现vue3数据双向绑定原理

    proxy实现vue3数据双向绑定原理

    这篇文章主要介绍了proxy实现vue3数据双向绑定原理,文章以介绍proxy的优点开始展开全文内容,围绕proxy实现vue3数据双向绑定的相关资料,,需要的朋友可以参考一下
    2021-12-12
  • vue3使用flv.js播放推流视频的示例代码

    vue3使用flv.js播放推流视频的示例代码

    本文主要介绍了vue3使用flv.js播放推流视频的示例代码,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习学习吧
    2023-05-05
  • Vue v-for中的 input 或 select的值发生改变时触发事件操作

    Vue v-for中的 input 或 select的值发生改变时触发事件操作

    这篇文章主要介绍了Vue v-for中的 input 或 select的值发生改变时触发事件操作,具有很好的参考价值,希望对大家有所帮助。一起跟随小编过来看看吧
    2020-08-08

最新评论