You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Typewriter JS重复运行样式丢失、文本缩短、性能下降问题求助

问题根源

  • 样式丢失:每次重启时直接从当前DOM节点读取innerHTML作为原始内容,首次打字完成后DOM内已经没有原始带class的span标签结构,后续拿到的只有纯文本,自然丢失样式。
  • 字符逐次少1:打字循环的终止条件为cursorPosition < HTML.length - 1,最后一个字符永远不会被输出,且每次重启读取的DOM内容本身就比上一次短1位,导致重复运行后字符越来越短。
  • 任务堆积卡顿:两个原因,一是setTimeout(restart(), 5000)写法错误,加括号会立即执行restart函数而非等待5秒,相当于打字到末尾立刻递归重启,无限生成定时器;二是没有存储定时器ID做清理,上一轮未执行的定时器会一直留在队列里,重复次数越多任务越多就越卡。

修正方案

  1. 提前将原始的带样式的HTML内容存到全局变量,不要每次重启都从DOM读取
  2. 修正setTimeout传参,传函数引用而非直接执行函数
  3. 存储每次生成的定时器ID,重启前清空上一轮的所有定时器,避免任务堆积
  4. 调整循环判断条件,输出全部字符

修正后完整JS代码

// 提前缓存原始带样式的HTML内容,不要从动态修改的DOM读取
const originalHTML = document.getElementById("typewriter").innerHTML;
// 存储定时器ID,用于清理
let timerId = null;

function setupTypewriter(t) {
  // 用缓存的原始HTML,不要用t.innerHTML
  var HTML = originalHTML;

  t.innerHTML = "";

  var cursorPosition = 0,
    tag = "",
    writingTag = false,
    tagOpen = false,
    typeSpeed = 100,
    tempTypeSpeed = 0;

  var type = function () {
    if (writingTag === true) {
      tag += HTML[cursorPosition];
    }

    if (HTML[cursorPosition] === "<") {
      tempTypeSpeed = 0;
      if (tagOpen) {
        tagOpen = false;
        writingTag = true;
      } else {
        tag = "";
        tagOpen = true;
        writingTag = true;
        tag += HTML[cursorPosition];
      }
    }
    if (!writingTag && tagOpen) {
      tag.innerHTML += HTML[cursorPosition];
    }
    if (!writingTag && !tagOpen) {
      if (HTML[cursorPosition] === " ") {
        tempTypeSpeed = 0;
      } else {
        tempTypeSpeed = Math.random() * typeSpeed + 50;
      }
      t.innerHTML += HTML[cursorPosition];
    }
    if (writingTag === true && HTML[cursorPosition] === ">") {
      tempTypeSpeed = Math.random() * typeSpeed + 50;
      writingTag = false;
      if (tagOpen) {
        var newSpan = document.createElement("span");
        t.appendChild(newSpan);
        newSpan.innerHTML = tag;
        tag = newSpan.firstChild;
      }
    }

    cursorPosition += 1;
    // 调整判断条件,输出全部字符
    if (cursorPosition < HTML.length) {
      // 存储定时器ID
      timerId = setTimeout(type, tempTypeSpeed);
    }

    if (cursorPosition == HTML.length) {  
      // 传函数引用,不要加括号,延迟5秒执行重启
      timerId = setTimeout(restart, 5000);
    }
  };

  return {
    type: type,
  };
}

let typer = document.getElementById("typewriter");
let typewriter = setupTypewriter(typer);
typewriter.type();

function restart() {
  // 重启前清空上一轮的所有定时器,避免任务堆积
  clearTimeout(timerId);
  typewriter = setupTypewriter(typer);
  typewriter.type();
}

内容的提问来源于stack exchange,提问作者Eddy

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.10.05 12:36:03