Skip to main content

倒计时

react

这里可以体会到 state 和 ref 的区别

ref 是一份容器,可以被替换不一样的内容,但是对容器的访问能一直保持同一个

类似 state 中存储 {current:1}而且修改时不会触发页面渲染(减少不必要的渲染)

因此 可以用它来存储那些不需要触发重新渲染的状态,例如计时器的 ID (计时器本身独立于渲染逻辑)

坏处是多个 ref 渲染不统一

const [time, setTime] = useState(100);
const timeRef = useRef();
useEffect(() => {
if (time && time !== 0) {
timeRef.current = setTimeout(() => {
setTime((time) => time - 1);
}, 1000);
}
// 组件重新更新时,就是setTime完,所以之前的计时器可以卸载,计时器本身一定是会在结束触发set的
return () => {
clearTimeout(timeRef.current);
};
// 在react中可以利用监听time状态重复创建定时器
// 在vue中必须使用setTimeInterval或watch
}, [time]);

Vue

<template>
<div>
<button :disabled="isDisabled" @click="startCountdown">
{{ buttonText }}
</button>
</div>
</template>

<script>
import { ref, onMounted, onUnmounted } from "vue";

export default {
setup() {
const countdownTime = ref(60); // 倒计时时间,单位秒
const buttonText = ref("获取验证码");
const isDisabled = ref(false);
let timer = null;

const startCountdown = () => {
if (isDisabled.value) return;

isDisabled.value = true;
buttonText.value = `${countdownTime.value}秒后重试`;

timer = setInterval(() => {
if (countdownTime.value > 1) {
countdownTime.value -= 1;
buttonText.value = `${countdownTime.value}秒后重试`;
} else {
clearInterval(timer);
buttonText.value = "获取验证码";
isDisabled.value = false;
countdownTime.value = 60; // 重置倒计时时间
}
}, 1000);
};

onUnmounted(() => {
if (timer) {
clearInterval(timer);
}
});

return {
buttonText,
isDisabled,
startCountdown,
};
},
};
</script>

<style scoped>
button {
padding: 10px 20px;
font-size: 16px;
}
</style>