news 2026/5/31 1:00:28

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/28 13:59:09

Rembg抠图实战:复杂纹理背景的处理方法

Rembg抠图实战&#xff1a;复杂纹理背景的处理方法 1. 引言&#xff1a;智能万能抠图 - Rembg 在图像处理领域&#xff0c;精准、高效地去除背景一直是设计师、电商运营和AI开发者的核心需求。传统手动抠图耗时耗力&#xff0c;而基于深度学习的自动去背技术正逐步成为主流。…

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

Rembg WebUI定制开发:界面美化与功能扩展

Rembg WebUI定制开发&#xff1a;界面美化与功能扩展 1. 背景与需求分析 1.1 智能万能抠图 - Rembg 在图像处理领域&#xff0c;自动去背景是一项高频且关键的需求。无论是电商商品图精修、社交媒体内容创作&#xff0c;还是设计素材提取&#xff0c;传统手动抠图效率低下&a…

作者头像 李华
网站建设 2026/5/30 23:19:57

Deepoc具身模型外拓板:春节居家,让智能机器人成为您的贴心管家

春节将至&#xff0c;当万家团圆、共享天伦之时&#xff0c;是否曾为繁琐的家务劳动而烦恼&#xff1f;是否希望有个得力的助手&#xff0c;让您从家务中解脱&#xff0c;全心享受温馨的团圆时光&#xff1f;Deepoc具身模型外拓板&#xff0c;正是为您量身打造的智能管家&#…

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

Rembg部署实践:云服务器配置指南

Rembg部署实践&#xff1a;云服务器配置指南 1. 引言 1.1 智能万能抠图 - Rembg 在图像处理与内容创作领域&#xff0c;精准、高效的背景去除技术一直是核心需求。无论是电商产品精修、社交媒体内容制作&#xff0c;还是AI艺术生成&#xff0c;自动抠图能力都直接影响最终输…

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

轻松玩转Qwen2.5-7B-Instruct|本地化部署与结构化输出实践指南

轻松玩转Qwen2.5-7B-Instruct&#xff5c;本地化部署与结构化输出实践指南 一、引言&#xff1a;为什么选择 Qwen2.5-7B-Instruct 做本地化部署&#xff1f; 在当前大模型快速迭代的背景下&#xff0c;如何将高性能语言模型高效、安全地落地到实际业务中&#xff0c;成为开发…

作者头像 李华
网站建设 2026/5/30 19:32:21

ResNet18多版本评测:v1/v2全对比,云端低成本完成

ResNet18多版本评测&#xff1a;v1/v2全对比&#xff0c;云端低成本完成 引言&#xff1a;为什么选择ResNet18&#xff1f; ResNet18作为计算机视觉领域的经典模型&#xff0c;凭借其轻量级结构和残差连接设计&#xff0c;至今仍是图像分类任务的首选基准模型。但对于刚入门的…

作者头像 李华