使用vue3实现简单的滑块组件
滑块组件主要是利用鼠标事件,让滑块跟着鼠标跟着x轴动,效果如下。
创建了一个名为 CustomSlider
的自定义滑块组件。它接受 min
、max
和 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-cli并创建第一个vue-cli应用程序
vue-cli这个构建工具大大降低了webpack的使用难度,支持热更新,有webpack-dev-server的支持,相当于启动了一个请求服务器,给你搭建了一个测试环境,下面这篇文章主要给大家介绍了关于安装vue-cli并创建第一个vue-cli应用程序的相关资料,需要的朋友可以参考下2022-08-08
最新评论