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>
相关推荐
SoaringHeart5 小时前
Flutter调试组件:打印任意组件尺寸位置信息 NRenderBox
前端·flutter
晚风予星5 小时前
Ant Design Token Lens 迎来了全面升级!支持在 .tsx 或 .ts 文件中直接使用 Design Token
前端·react.js·visual studio code
sunny_6 小时前
⚡️ vite-plugin-oxc:从 Babel 到 Oxc,我为 Vite 写了一个高性能编译插件
前端·webpack·架构
GIS之路6 小时前
ArcPy 开发环境搭建
前端
林小帅7 小时前
【笔记】OpenClaw 架构浅析
前端·agent
林小帅8 小时前
【笔记】OpenClaw 生态系统的多语言实现对比分析
前端·agent
程序猿的程8 小时前
开源一个 React 股票 K 线图组件,传个股票代码就能画图
前端·javascript
不爱说话郭德纲8 小时前
告别漫长的HbuilderX云打包排队!uni-app x 安卓本地打包保姆级教程(附白屏、包体积过大排坑指南)
android·前端·uni-app
大雨还洅下9 小时前
前端JS: 虚拟dom是什么? 原理? 优缺点?
javascript
唐叔在学习9 小时前
[前端特效] 左滑显示按钮的实现介绍
前端·javascript