vue3 Element-plus setup ts 滑动组件验证
效果如下:
vue3 滑块验证演示
vue3 滑块验证演示<template> <div class="slider-verification" ref="sliderContainer"> <div class="slider-left-bg" :style="sliderLeftWidthStyle"></div> <div class="prompt-text" :style="verifySuccess ? promptTextStyleSuccess: {}"> { { verifySuccess ? 验证通过 : 向右拖动滑块进行验证 }} </div> <div ref="slider" @mousedown="mouseDownHandler($event)" :class="{slider-verify-success:verifySuccess}" class="slider" :style="sliderToLeftStyle"> <el-icon v-if="verifySuccess" :size="iconSize" color="#fff"> <CircleCheck /> </el-icon> <el-icon v-else :size="iconSize" color="#fff"> <DArrowRight /> </el-icon> </div> </div> </template>
<script setup lang="ts"> interface Props { multiple: number, promptTextStyleSuccess: Record<any, any> } interface Emits { (e: statusChange, val: boolean): void } const props = withDefaults(defineProps<Props>(), { multiple: 2, promptTextStyleSuccess: () => ({ color: #ffffff }) }) const emits = defineEmits<Emits>() let sliderState = ref(false) let verifySuccess = ref(false) let beginClientX = ref(0) let maxWidth = ref(0) const iconSize = ref(22) const slideWidth = ref(0) //鼠标移动 const mouseMoveHandler = (e) => { if (sliderState.value) { let width = (e.clientX - beginClientX.value) / props.multiple; if (width > 0 && width <= maxWidth.value) { slideWidth.value = width } else if (width > maxWidth.value) { slideWidth.value = maxWidth.value verifySuccessFun(); } } } //鼠标松开 const mouseUpHandler = (e) => { sliderState.value = false; let width = (e.clientX - beginClientX.value) / props.multiple; if (width < maxWidth.value) { slideWidth.value = 0 } } //验证通过 const verifySuccessFun = () => { verifySuccess.value = true emits(statusChange, true) document.getElementsByTagName(html)[0].removeEventListener(mousemove, mouseMoveHandler); document.getElementsByTagName(html)[0].removeEventListener(mouseup, mouseUpHandler); slideWidth.value = maxWidth.value } const slider = ref(null) const sliderContainer = ref(null) //事件监听 const addListener = () => { document.getElementsByTagName(html)[0].addEventListener(mousemove, mouseMoveHandler); document.getElementsByTagName(html)[0].addEventListener(mouseup, mouseUpHandler) } // 重置 const reset = () => { addListener() emits(statusChange, false) beginClientX.value = 0 sliderState.value = false verifySuccess.value = false slideWidth.value = 0 } // 鼠标在滑块上按下事件 const mouseDownHandler = (e) => { if (!verifySuccess.value) { sliderState.value = true; beginClientX.value = e.clientX; } } onMounted(() => { maxWidth.value = sliderContainer.value.offsetWidth - slider.value.offsetWidth; addListener() }) const sliderToLeftStyle = computed(() => ({ left: slideWidth.value + px })) const sliderLeftWidthStyle = computed(() => ({ width: slideWidth.value + px })) defineExpose({ reset }) </script>
.slider-verification { position: relative; background-color: var(--ep-color-primary); width: 100%; height: 100%; line-height: 48px; text-align: center; user-select: none; } .slider { position: absolute; top: 0; width: 42px; height: 48px; cursor: move; background: var(--ep-color-primary-light-5); background-size: 30px 30px; display: flex; align-items: center; justify-content: center; } .slider-verify-success { background: var(--ep-color-primary-light-5); background-size: 30px 30px; } //滑块滑过区域的样式 .slider-left-bg { // background-color: rgba(0, 235, 255, 0.42); background: rgba(0, 235, 255, 0.3); width: 0; height: 100%; } //提示文本样式 .prompt-text { position: absolute; top: 0; left: 0; width: 100%; height: 48px; text-align: center; font-size: 14px; line-height: 48px; color: #ffffff; }