Vue3.2+ sliding verification component, universal for pc/mobile phone, plug and play
I. Introduction
Vue has been updated to 3.2+, uses script setup attribute syntax, supports typescript, but most of the existing sliding verification components on the Internet are old versions, and do not support touch, so I decided to write one:
- Support vue3.2+ syntax
- support typescript
- Support pc/mobile phone (automatic adaptation)
- plug and play
The sliding verification component is convenient for everyone. Of course, this is only a static verification. If dynamic verification is required, it needs to cooperate with the backend.
2. Results display
3. Use of components
import component, and then <dragVerify v-model:value="form.isVerifyPass"></dragVerify>
use it, which supports attributes v-model:value
for the two-way binding result :
- successIcon success icon {string} default value 'iconfont icon-status-nor'
- successText success text string} default value 'authentication successful'
- startIcon start icon {string} default 'iconfont icon-login-slid'
- startText start text {string} default value 'drag the slider to the far right'
<template>
<div class="test">
<h3>vue3.2+ 滑动验证组件,pc/手机通用</h3>
<div class="content">
<dragVerify v-model:value="form.isVerifyPass"></dragVerify>
</div>
<div>校验结果:{
{ form.isVerifyPass }}</div>
</div>
</template>
<script lang="ts" setup>
import {
reactive } from 'vue'
import dragVerify from '@/components/dragVerify.vue'
// 提交表单数据
const form = reactive({
isVerifyPass: false, // 滑块验证结果
})
</script>
Four, vue3.2+ sliding verification component source code
<template>
<div class="drag-verify">
<div class="range" :class="verifyResult ? 'success' : ''">
<div class="block" @mousedown="onStart" @touchstart="onStart">
<i :class="verifyResult ? successIcon : startIcon"></i>
</div>
<span class="text">{
{ verifyResult ? successText : startText }}</span>
</div>
</div>
</template>
<script lang="ts" setup>
import {
ref } from 'vue'
const emit = defineEmits(['update:value'])
defineProps({
value: {
type: Boolean,
defalut: false,
},
// 成功图标
successIcon: {
type: String,
default: 'iconfont icon-status-nor',
},
// 成功文字
successText: {
type: String,
default: '验证成功',
},
// 开始的图标
startIcon: {
type: String,
default: 'iconfont icon-login-slid',
},
// 开始的文字
startText: {
type: String,
default: '拖动滑块到最右边',
},
})
const verifyResult = ref(false) // 验证结果
const isTouch = 'ontouchstart' in document.documentElement
const moveEvent = isTouch ? 'touchmove' : 'mousemove'
const upEvent = isTouch ? 'touchend' : 'mouseup'
// 滑块触摸开始
const onStart = (ev: MouseEvent | TouchEvent) => {
let disX = 0 // 滑块移动距离
const iconWidth = 40 // 滑动图标宽度
const ele = document.querySelector('.drag-verify .block') as HTMLElement
const startX = (ev as MouseEvent).clientX || (ev as TouchEvent).touches[0].pageX
const parentWidth = ele.offsetWidth
const MaxX = parentWidth - iconWidth
if (verifyResult.value) {
return false
}
// 滑块触摸移动
const onMove = (e: MouseEvent | TouchEvent) => {
const endX = (e as MouseEvent).clientX || (e as TouchEvent).touches[0].pageX
disX = endX - startX
if (disX <= 0) {
disX = 0
}
if (disX >= MaxX - iconWidth) {
disX = MaxX
}
ele.style.transition = '.1s all'
ele.style.transform = `translateX(${
disX}px)`
}
// 滑块触摸结束
const onEnd = () => {
if (disX !== MaxX) {
ele.style.transition = '.5s all'
ele.style.transform = 'translateX(0)'
} else {
// 执行成功
verifyResult.value = true
emit('update:value', verifyResult.value)
}
document.removeEventListener(moveEvent, onMove)
document.removeEventListener(upEvent, onEnd)
}
document.addEventListener(moveEvent, onMove)
document.addEventListener(upEvent, onEnd)
}
</script>
<style lang="scss" scoped>
$color-primary: #03c5e5;
@mixin flex {
display: flex;
justify-content: center;
align-items: center;
}
.drag-verify {
width: 100%;
.range {
background-color: #ececee;
position: relative;
border-radius: 4px;
transition: 1s all;
user-select: none;
color: #666;
overflow: hidden;
@include flex;
height: 40px;
&.success {
background-color: $color-primary;
color: #fff;
.text {
position: relative;
z-index: 1;
}
.block i {
color: $color-primary;
}
}
.block {
display: block;
position: absolute;
left: calc(-100% + 40px);
width: 100%;
height: 100%;
background: $color-primary;
border-radius: 4px;
overflow: hidden;
i {
position: absolute;
right: 0;
width: 40px;
height: 100%;
font-size: 20px;
color: #c8c9cc;
background-color: #fff;
border: 1px solid #e5e5e5;
border-radius: 4px;
cursor: pointer;
@include flex;
}
}
}
}
</style>
5. Finally, give a thumbs up
If it helps you, 点个赞再走
!