共计 2275 个字符,预计需要花费 6 分钟才能阅读完成。
Vant 没有提供倒计时按钮组件,手动实现一下。
// CountDownButton.vue 实现
<template>
<Button
style="min-width: 80px;"
size="small"
type="primary"
:disabled="countDownButtonArgs.timing"
@click="emit('click', successCallback)"
>{{loading ? loadingText : countDownButtonArgs.timing ? countDownButtonArgs.count : buttonText}}</Button>
</template>
<script setup lang="ts">
import {reactive} from 'vue'
import {Button} from 'vant'
const props = defineProps({
maxSecondNum: {
type: Number,
default: 60
},
buttonText: {
type: String,
default: '获取验证码'
},
loadingText: {
type: String,
default: '发送中'
},
loading: {
type: Boolean,
default: false
}
})
type EmitsType = {(e: 'click', successCallback: () => void): void }
const emit = defineEmits<EmitsType>()
const countDownButtonArgs = reactive<{timing: boolean; count: number}>({
timing: false,
count: 0
})
const successCallback = () => {
countDownButtonArgs.timing = true
countDownButtonArgs.count = props.maxSecondNum
const timer = setInterval(() => {const { count} = countDownButtonArgs
if (count > 0 && count <= props.maxSecondNum) {countDownButtonArgs.count--;} else {
countDownButtonArgs.timing = false
clearInterval(timer)
countDownButtonArgs.count = 0
}
}, 1000)
}
</script>
<style lang="less">
</style>
// 应用举例
<template>
<div>
<NavBar title="用户登录"></NavBar>
<Form @submit="onLogin">
<CellGroup inset>
<Field
v-model="phone"
name="tel"
label="手机号"
:rules="[{required: true, message:' 请输出 '}]"
/>
<Field
v-model="code"
type="password"
name="password"
label="验证码"
:rules="[{required: true, message:' 请输出 '}]"
>
<template #button>
<CountDownButton :loading="loading" @click="getCodeFn"></CountDownButton>
</template>
</Field>
</CellGroup>
<div style="margin: 16px;">
<Button round block type="primary" native-type="submit"> 登录 </Button>
</div>
</Form>
</div>
</template>
<script setup lang="ts">
import {ref} from "vue";
import {Form, Field, CellGroup, Button, NavBar, Toast} from 'vant'
import CountDownButton from '../../../components/CountDownButton.vue'
import {sendSmsCode, smsLogin} from './api'
import {useRouter} from 'vue-router'
const router = useRouter()
const phone = ref('');
const code = ref('');
const onLogin = async () => {const b = await smsLogin(phone.value, code.value)
if (b) {Toast('登录胜利')
router.push('/tvs/home')
}
};
const loading = ref(false)
const getCodeFn = async (successCallback: () => void) => {if (!phone.value) {Toast('请输出手机号'); return; }
loading.value = true
const b = await sendSmsCode(phone.value)
loading.value = false
successCallback()
if (b) {Toast('验证码发送胜利'); }
}
</script>
<style lang="less">
</style>
成果如下
正文完