废话不多说 直接上代码 读props 来引入组件即可
javascript
<template>
<div class="typewriter-text">
{{ displayedText }}<span class="cursor">|</span>
</div>
</template>
<script setup>
import { ref, watch, onMounted, onUnmounted } from 'vue'
const props = defineProps({
// 完整的文字
text: {
type: String,
default: ''
},
// 打字的速度
speed: {
type: Number,
default: 50
},
// 是否自动开始
autoStart: {
type: Boolean,
default: true
},
// 是否可见
visible: {
type: Boolean,
default: true
}
})
const displayedText = ref('')
const typewriterTimer = ref(null)
function startTypewriter () {
displayedText.value = ''
let index = 0
if (typewriterTimer.value) {
clearInterval(typewriterTimer.value)
}
typewriterTimer.value = setInterval(() => {
if (index < props.text.length) {
displayedText.value += props.text[index]
index++
} else {
if (typewriterTimer.value) {
clearInterval(typewriterTimer.value)
typewriterTimer.value = null
}
}
}, props.speed)
}
function resetTypewriter () {
if (typewriterTimer.value) {
clearInterval(typewriterTimer.value)
typewriterTimer.value = null
}
displayedText.value = ''
}
// 监听visible,控制打字机效果的开始和重置
watch(() => props.visible, (newVal) => {
if (newVal) {
// autoStart为true的时候自动开始
if (props.autoStart && props.text) {
resetTypewriter()
startTypewriter()
}
} else {
// 重置
resetTypewriter()
}
}, { immediate: true })
// 监听文字,文字改变后重新开始
watch(() => props.text, () => {
if (props.autoStart && props.visible && props.text) {
resetTypewriter()
startTypewriter()
}
}, { immediate: false })
onMounted(() => {
if (props.autoStart && props.visible && props.text) {
startTypewriter()
}
})
onUnmounted(() => {
resetTypewriter()
})
defineExpose({
start: startTypewriter,
reset: resetTypewriter
})
</script>
<style lang="less" scoped>
.typewriter-text {
font-size: 14px;
line-height: 1.8;
color: #333;
min-height: 100px;
white-space: pre-wrap;
word-wrap: break-word;
}
.typewriter-text .cursor {
display: inline-block;
margin-left: 2px;
animation: blink 1s infinite;
color: #3b82f6;
font-weight: bold;
}
@keyframes blink {
0%, 50% {
opacity: 1;
}
51%, 100% {
opacity: 0;
}
}
</style>