news 2026/5/9 10:57:32

Vue3 实现超丝滑打字机效果组件 - 进阶

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
Vue3 实现超丝滑打字机效果组件 - 进阶

🔥 Vue3 实现超丝滑打字机效果组件(可复用、高定制)

在前端开发中,打字机效果能极大提升页面的交互趣味性和视觉体验,比如 AI 聊天回复、个性化介绍页等场景都非常适用。本文将分享一个基于 Vue3 + Composition API 开发的高性能、高定制化打字机组件,支持打字/删除循环、光标闪烁、自定义样式等核心功能,且代码结构清晰、易于扩展。

🎯 组件特性

  • ✅ 自定义打字速度、删除速度、循环延迟
  • ✅ 支持光标显示/隐藏、闪烁效果开关
  • ✅ 打字完成后自动删除(可选)+ 循环播放
  • ✅ 完全自定义样式(字体、颜色、大小等)
  • ✅ 暴露控制方法(开始/暂停),支持手动干预
  • ✅ 无第三方依赖,纯原生 Vue3 实现
  • ✅ 性能优化:组件卸载自动清理定时器,避免内存泄漏

📝 完整组件代码

<template><divclass="typewriter-container":style="fontsConStyle"><!--打字文本-逐字符渲染--><spanclass="typewriter-text"><span v-for="(char, index) in displayedText":key="index"class="character":data-index="index">{{char}}</span></span><!--光标-精准控制显示/闪烁--><span v-if="showCursor && isCursorVisible"class="cursor":class="{ 'blink': showBlinkCursor }"aria-hidden="true"/></div></template><script setup>import{ref,onMounted,onBeforeUnmount,computed,watch,watchEffect}from"vue";// 组件 Props 定义(带完整校验)constprops=defineProps({// 要显示的文本内容text:{type:String,required:true,default:""},// 打字速度(ms/字符)speed:{type:Number,default:80,validator:(value)=>value>0},// 是否显示光标showCursor:{type:Boolean,default:true},// 光标是否闪烁blinkCursor:{type:Boolean,default:true},// 是否自动开始打字autoStart:{type:Boolean,default:true},// 是否循环播放loop:{type:Boolean,default:false},// 循环延迟(打字完成后等待时间)loopDelay:{type:Number,default:1000,validator:(value)=>value>=0},// 容器样式(自定义字体、颜色等)fontsConStyle:{type:Object,default:()=>({fontSize:"2rem",fontFamily:"'Courier New', monospace",color:"#333",lineHeight:"1.5"})},// 是否开启删除效果deleteEffect:{type:Boolean,default:false},// 删除速度(ms/字符)deleteSpeed:{type:Number,default:30,validator:(value)=>value>0},// 字符入场动画开关charAnimation:{type:Boolean,default:true}});// 响应式状态constdisplayedText=ref("");// 当前显示的文本constcurrentIndex=ref(0);// 当前字符索引constisPlaying=ref(false);// 是否正在播放constisDeleting=ref(false);// 是否正在删除constisCursorVisible=ref(true);// 光标是否显示// 定时器标识(用于清理)letintervalId=null;lettimeoutId=null;letcursorTimer=null;// 计算属性:控制光标闪烁状态constshowBlinkCursor=computed(()=>{returnprops.blinkCursor&&!isDeleting.value&&(displayedText.value.length===props.text.length||displayedText.value.length===0);});// 工具函数:清除所有定时器constclearAllTimers=()=>{if(intervalId)clearInterval(intervalId);if(timeoutId)clearTimeout(timeoutId);if(cursorTimer)clearInterval(cursorTimer);intervalId=null;timeoutId=null;cursorTimer=null;};// 核心方法:开始打字conststartTyping=()=>{// 重置状态clearAllTimers();isPlaying.value=true;isDeleting.value=false;currentIndex.value=0;displayedText.value="";isCursorVisible.value=true;// 打字逻辑intervalId=setInterval(()=>{if(currentIndex.value<props.text.length){displayedText.value=props.text.substring(0,currentIndex.value+1);currentIndex.value++;}else{// 打字完成clearInterval(intervalId);isPlaying.value=false;// 循环逻辑if(props.loop){if(props.deleteEffect){timeoutId=setTimeout(startDeleting,props.loopDelay);}else{timeoutId=setTimeout(startTyping,props.loopDelay);}}}},props.speed);};// 核心方法:开始删除conststartDeleting=()=>{clearAllTimers();isDeleting.value=true;intervalId=setInterval(()=>{if(currentIndex.value>0){currentIndex.value--;displayedText.value=props.text.substring(0,currentIndex.value);}else{// 删除完成clearInterval(intervalId);isDeleting.value=false;// 循环打字if(props.loop){timeoutId=setTimeout(startTyping,props.loopDelay);}else{isCursorVisible.value=false;// 非循环模式下删除完成隐藏光标}}},props.deleteSpeed);};// 监听文本变化:自动重启打字(适配动态文本场景)watch(()=>props.text,(newText)=>{if(newText&&props.autoStart){startTyping();}},{immediate:true});// 初始化光标闪烁(非闪烁模式下固定显示)watchEffect(()=>{if(props.showCursor&&!cursorTimer){cursorTimer=setInterval(()=>{if(!showBlinkCursor.value){isCursorVisible.value=true;}else{isCursorVisible.value=!isCursorVisible.value;}},500);}});// 组件挂载:自动开始打字onMounted(()=>{if(props.autoStart&&props.text){startTyping();}});// 组件卸载:清理所有定时器(避免内存泄漏)onBeforeUnmount(()=>{clearAllTimers();});// 暴露组件方法(供父组件调用)defineExpose({start:startTyping,// 手动开始pause:clearAllTimers,// 暂停restart:()=>{// 重启clearAllTimers();startTyping();},isPlaying,// 当前播放状态isDeleting// 当前删除状态});</script><style scoped>/* 容器样式 - 适配行内/块级显示 */.typewriter-container{display:inline-flex;align-items:center;position:relative;font-size:inherit;line-height:inherit;font-family:inherit;white-space:pre-wrap;/* 支持换行符 */word-break:break-all;/* 防止长文本溢出 */}/* 文本容器 */.typewriter-text{display:inline;font-size:inherit;line-height:inherit;font-family:inherit;color:inherit;}/* 字符样式 - 入场动画 */.character{display:inline-block;animation:typeIn0.1s ease-out forwards;opacity:0;}/* 字符入场动画 */@keyframes typeIn{0%{transform:translateY(5px);opacity:0;}100%{transform:translateY(0);opacity:1;}}/* 光标样式 - 垂直居中优化 */.cursor{display:inline-block;width:2px;height:1.2em;/* 匹配字体高度 */background-color:currentColor;margin-left:2px;vertical-align:middle;position:relative;top:0;opacity:1;}/* 光标闪烁动画 */.cursor.blink{animation:blink 1s infinite step-end;}@keyframes blink{0%,100%{opacity:1;}50%{opacity:0;}}/* 禁用字符动画的样式 */:deep(.character){animation:none!important;opacity:1!important;}</style>

🚀 核心优化点说明

1. 功能增强

  • 新增charAnimation属性:可开关字符入场动画,适配不同场景
  • 支持动态文本:监听text属性变化,文本更新自动重启打字
  • 优化光标逻辑:非闪烁模式下光标固定显示,避免闪烁干扰
  • 新增restart方法:支持手动重启打字效果
  • 文本换行支持:添加white-space: pre-wrap,兼容带换行符的文本

2. 性能优化

  • 定时器统一管理:所有定时器集中清理,避免内存泄漏
  • 减少不必要渲染:通过watchEffect精准控制光标定时器创建/销毁
  • 样式优化:使用currentColor继承文本颜色,光标颜色与文本一致
  • 边界处理:添加word-break: break-all,防止长文本溢出

3. 代码健壮性

  • 完善 Prop 校验:所有数值类型添加范围校验,避免非法值
  • 状态重置:每次开始打字前重置所有状态,避免多轮执行冲突
  • 注释完善:关键逻辑添加注释,提升代码可读性

📖 使用示例

基础使用

<template><Typewriter text="Hello Vue3! 这是一个超丝滑的打字机效果组件✨"speed="50"/></template><script setup>importTypewriterfrom'./components/Typewriter.vue';</script>

高级使用(循环+删除效果)

<template><div><Typewriter ref="typewriterRef"text="Vue3 打字机组件 | 支持循环删除 | 自定义样式":speed="60":deleteSpeed="40":loop="true":deleteEffect="true":loopDelay="1500":fontsConStyle="{fontSize:'1.5rem',color:'#409eff',fontFamily:'微软雅黑'}"/><button @click="handleRestart">重启打字</button></div></template><script setup>import{ref}from'vue';importTypewriterfrom'./components/Typewriter.vue';consttypewriterRef=ref();// 手动重启打字consthandleRestart=()=>{typewriterRef.value.restart();};</script>

🎨 样式自定义说明

属性说明默认值
fontSize字体大小2rem
fontFamily字体‘Courier New’, monospace
color文本颜色#333
lineHeight行高1.5

你可以通过fontsConStyle属性完全自定义组件样式,例如:

fontsConStyle:{fontSize:"18px",color:"#e6a23c",fontWeight:"bold",background:"#f5f7fa",padding:"10px 15px",borderRadius:"8px"}

🛠️ 扩展方向

  1. 自定义字符动画:通过 Prop 传入动画类名,支持不同的字符入场效果
  2. 分段打字:支持数组形式的文本,分段打字+间隔
  3. 速度渐变:实现打字速度由快到慢/由慢到快的效果
  4. 暂停/继续:扩展暂停后继续打字的功能(记录当前索引)
  5. 结合 AI 流式响应:对接 AI 接口的流式返回,实时更新打字文本

📌 总结

这个打字机组件基于 Vue3 Composition API 开发,具备高复用性、高定制性的特点,核心优化点如下:

  1. 完善的定时器管理,避免内存泄漏
  2. 精准的状态控制,支持打字/删除/循环全流程
  3. 灵活的样式自定义,适配不同业务场景
  4. 暴露控制方法,支持父组件手动干预

组件可直接集成到 Vue3 项目中,适用于 AI 聊天、个人主页、产品介绍等需要打字机效果的场景,开箱即用!

版权声明: 本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若内容造成侵权/违法违规/事实不符,请联系邮箱:809451989@qq.com进行投诉反馈,一经查实,立即删除!
网站建设 2026/5/9 7:31:30

零基础学Rembg:图像分割入门完整指南

零基础学Rembg&#xff1a;图像分割入门完整指南 1. 引言&#xff1a;智能万能抠图 - Rembg 在数字内容创作日益普及的今天&#xff0c;图像去背景&#xff08;抠图&#xff09;已成为设计师、电商运营、AI开发者等群体的高频需求。传统手动抠图耗时耗力&#xff0c;而基于深…

作者头像 李华
网站建设 2026/5/5 9:32:59

大模型微调实战——对事项做文本分类

上篇文章介绍了大模型微调的一些“心法”和注意事项&#xff0c;也算是进行了预热。本文将以DeepSeek-R1-Distill-Qwen-7B模型为例&#xff0c;详细介绍如何在NVIDIA RTX 4090&#xff08;消费级GPU&#xff0c;打游戏用的水平&#xff0c;不需要非常专业的A100、H100这种GPU&a…

作者头像 李华
网站建设 2026/5/5 19:41:37

手把手搭建本地 RAG 知识库!实现文档秒检索

上一篇我们分享了如何在本地电脑搭建基础 RAG 系统&#xff0c;支持调用本地或公有云大模型处理各类任务。 这一次&#xff0c;我们聚焦核心需求“创建专属自己的RAG知识库”&#xff0c;让本地文档检索像搜索网页一样高效&#xff0c;全程用开源模型 nomic-embed-text 搞定文档…

作者头像 李华
网站建设 2026/5/7 4:53:56

Qwen2.5-7B-Instruct镜像详解|轻松实现SQL与邮件格式化生成

Qwen2.5-7B-Instruct镜像详解&#xff5c;轻松实现SQL与邮件格式化生成 一、引言&#xff1a;为何选择Qwen2.5-7B-Instruct进行结构化输出&#xff1f; 随着大语言模型在企业级应用中的深入落地&#xff0c;如何让模型输出可解析、可集成的结构化数据&#xff0c;已成为工程实…

作者头像 李华
网站建设 2026/5/9 2:57:35

LLM实战——微调Deepseek-Qwen模型

大家一定接触过不少大模型&#xff08;LLM&#xff09;&#xff0c;对ChatGPT、DeepSeek、Qwen等可以说是耳熟能详。这些通用大模型虽然可以拿来直接使用&#xff0c;但是对于一些“私域”的信息无法触及到&#xff0c;缺少相应的训练数据&#xff0c;普遍面临 “水土不服” 的…

作者头像 李华
网站建设 2026/5/6 13:17:28

提升大模型交互体验|Qwen2.5-7B-Instruct集成Chainlit实践

提升大模型交互体验&#xff5c;Qwen2.5-7B-Instruct集成Chainlit实践 一、引言&#xff1a;为何选择Chainlit构建大模型前端交互界面&#xff1f; 随着大语言模型&#xff08;LLM&#xff09;能力的持续进化&#xff0c;如何高效地与模型进行交互成为开发者关注的核心问题。…

作者头像 李华