vue实现即开即用的AI对话打字机效果

废话不多说 直接上代码 读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>
相关推荐
WeiXiao_Hyy1 天前
成为 Top 1% 的工程师
java·开发语言·javascript·经验分享·后端
吃杠碰小鸡1 天前
高中数学-数列-导数证明
前端·数学·算法
kingwebo'sZone1 天前
C#使用Aspose.Words把 word转成图片
前端·c#·word
xjt_09011 天前
基于 Vue 3 构建企业级 Web Components 组件库
前端·javascript·vue.js
我是伪码农1 天前
Vue 2.3
前端·javascript·vue.js
夜郎king1 天前
HTML5 SVG 实现日出日落动画与实时天气可视化
前端·html5·svg 日出日落
辰风沐阳1 天前
JavaScript 的宏任务和微任务
javascript
跳动的梦想家h1 天前
环境配置 + AI 提效双管齐下
java·vue.js·spring
夏幻灵1 天前
HTML5里最常用的十大标签
前端·html·html5
冰暮流星1 天前
javascript之二重循环练习
开发语言·javascript·数据库