news 2026/6/15 23:24:50

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/6/15 12:54:14

掌握Qwen2.5-7B微调技巧|基于LLaMA-Factory的参数高效调优

掌握Qwen2.5-7B微调技巧&#xff5c;基于LLaMA-Factory的参数高效调优 一、前言 随着大语言模型&#xff08;LLM&#xff09;在自然语言处理领域的广泛应用&#xff0c;如何高效地对预训练模型进行定制化微调成为开发者关注的核心问题。本文将围绕阿里云最新发布的 Qwen2.5-7B-…

作者头像 李华
网站建设 2026/6/15 13:53:03

『NAS』在绿联部署今日热榜-Dailyhot

点赞 关注 收藏 学会了 整理了一个NAS小专栏&#xff0c;有兴趣的工友可以关注一下 &#x1f449; 《NAS邪修》 Dailyhot 是一款开源的全网热榜聚合工具&#xff0c;能一站式汇聚 27 主流平台的实时热点&#xff0c;帮助用户快速掌握全网脉搏。 在NAS里可以利用Docker部署它…

作者头像 李华
网站建设 2026/6/15 16:04:28

Rembg抠图WebUI部署:零基础入门到精通

Rembg抠图WebUI部署&#xff1a;零基础入门到精通 1. 智能万能抠图 - Rembg 在图像处理与内容创作领域&#xff0c;背景去除是一项高频且关键的任务。无论是电商产品图精修、社交媒体素材制作&#xff0c;还是AI绘画中的角色提取&#xff0c;精准高效的抠图能力都直接影响最终…

作者头像 李华
网站建设 2026/6/15 20:54:16

详解Qwen2.5-7B-Instruct镜像的离线推理实现路径

详解Qwen2.5-7B-Instruct镜像的离线推理实现路径 引言&#xff1a;为何选择离线推理部署Qwen2.5-7B-Instruct&#xff1f; 在大模型落地实践中&#xff0c;离线推理正成为资源受限场景下的关键突破口。尤其对于参数量达76亿的Qwen2.5-7B-Instruct这类中等规模语言模型&#x…

作者头像 李华
网站建设 2026/6/15 13:56:05

ResNet18物体识别懒人方案:预置镜像一键部署,2块钱玩一下午

ResNet18物体识别懒人方案&#xff1a;预置镜像一键部署&#xff0c;2块钱玩一下午 1. 为什么选择ResNet18&#xff1f; ResNet18是计算机视觉领域的"瑞士军刀"&#xff0c;特别适合想快速验证物体识别效果的设计师和开发者。这个轻量级模型有三大优势&#xff1a;…

作者头像 李华