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>
相关推荐
用户69371750013849 小时前
Google 正在“收紧侧加载”:陌生 APK 安装或需等待 24 小时
android·前端
蓝帆傲亦9 小时前
Web 前端搜索文字高亮实现方法汇总
前端
用户69371750013849 小时前
Room 3.0:这次不是升级,是重来
android·前端·google
漫随流水10 小时前
旅游推荐系统(view.py)
前端·数据库·python·旅游
踩着两条虫11 小时前
VTJ.PRO 核心架构全公开!从设计稿到代码,揭秘AI智能体如何“听懂人话”
前端·vue.js·ai编程
jzlhll12312 小时前
kotlin Flow first() last()总结
开发语言·前端·kotlin
用头发抵命12 小时前
Vue 3 中优雅地集成 Video.js 播放器:从组件封装到功能定制
开发语言·javascript·ecmascript
蓝冰凌13 小时前
Vue 3 中 defineExpose 的行为【defineExpose暴露ref变量】详解:自动解包、响应性与实际使用
前端·javascript·vue.js
奔跑的呱呱牛13 小时前
generate-route-vue基于文件系统的 Vue Router 动态路由生成工具
前端·javascript·vue.js