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

Chrome扩展点击按钮注入定时器:append无效/insertAdjacentHTML报错

问题根源与解决方案

核心问题分析

  1. 定时器未触发:原代码里startTimer的调用逻辑绑在window.load事件上,只在页面初始加载时执行一次。点击按钮注入timer.html时,这个事件早就触发过了,不会重新执行定时器初始化,导致找不到新注入的#time元素,定时器自然启动不了。
  2. insertAdjacentHTML报错:insertAdjacentHTML要求第二个参数是HTML字符串,但你传了DOM元素injectedStuff,浏览器会把它强制转成字符串[object HTMLUnknownElement];另外你用document.createElement("element")创建自定义未知元素,属于完全没必要的冗余操作。
  3. 自动注入能正常工作,是因为它在页面加载阶段就完成了HTML注入,此时window.load触发时能找到#time元素。

修正步骤

步骤1:修复HTML注入逻辑

  • 删掉无用的自定义元素创建代码,直接把fetch拿到的HTML字符串注入目标节点;
  • 用insertAdjacentHTML就直接传HTML字符串,用append的话可以创建临时容器插入后再移动节点。

步骤2:调整定时器启动时机

  • 把定时器初始化逻辑封装成独立函数,在HTML注入完成后立刻调用,确保能获取到刚注入的#time元素。

步骤3:修正语法错误

  • 原代码里window.addEventListener('load', function (){ function () { ... } })有嵌套函数语法错误,还有注释闭合不规范的问题,直接修正。

完整修正代码

foreground.js

// 点击注入代码
window.onload = function () {
    document.getElementById("dd7975c81b0fac90f6bba640604bcb96").addEventListener("click", function () {
        injectElements_page();
    });
}

function injectElements_page() {
    fetch(chrome.runtime.getURL('timer/timer.html'))
    .then(response => response.text())
    .then(data => {
        // 修正目标元素选择器:getElementById不能带类名,改用querySelector
        const target = document.querySelector("#section-07b699970f7ada007b2ff68ce1050eb1.header");
        // 用insertAdjacentHTML直接注入HTML字符串
        target.insertAdjacentHTML('beforeend', data);
        
        // 注入完成后马上启动定时器
        initTimer();
    }).catch(err => {
        console.error('注入失败:', err);
    });
}

// 定时器函数
function startTimer(duration, display, callback) {
    let timer = duration;
    let minutes;
    let seconds;
    let interval = setInterval(function() {
        minutes = ('00' + parseInt(timer / 60, 10)).slice(-2);
        seconds = ('00' + parseInt(timer % 60, 10)).slice(-2);
        display.textContent = minutes + ":" + seconds;

        if (--timer < 0) {
            callback();
            clearInterval(interval);
        }
    }, 1000);
}

const onTimerEnded = () => {
    // alertTimeOver(); // -> 超时提示可在这里实现
    console.log('定时器结束');
}

// 独立的定时器初始化函数
function initTimer() {
    // 直接用15秒,避免60*0.24的浮点精度问题(结果是14.4,取整后是14秒,和timer.html的00:15不符)
    const fifteenSeconds = 15; 
    const display = document.querySelector('#time');
    if (display) { // 加个判断,防止找不到元素报错
        startTimer(fifteenSeconds, display, onTimerEnded);
    } else {
        console.error('未找到定时器显示元素');
    }
}

// 保留原自动注入逻辑
fetch(chrome.runtime.getURL('timer/timer.html')).then(r => r.text()).then(html => {
    if (window.location.toString().includes("sysparm_domain=null&sysparm_domain_scope=null")) {
        document.body.insertAdjacentHTML('beforebegin', html);
        initTimer(); // 自动注入后也调用初始化函数
    }
});

关键修正点说明

  • 目标元素选择器:原代码document.getElementById("section-xxx.header")错误,getElementById只能接收纯ID,不能带类名,改用querySelector("#section-xxx.header")选择「ID为section-xxx且带header类」的元素。
  • 定时器启动时机:在injectElements_page的fetch回调里,注入HTML后立即调用initTimer,确保新DOM已挂载。
  • insertAdjacentHTML参数:直接传data(HTML字符串)而非DOM元素,解决[object HTMLUnknownElement]报错。
  • 冗余代码移除:删掉var injectedStuff = document.createElement("element"),简化注入逻辑。
  • 精度问题修复:原代码60 * 0.24计算结果是14.4,取整后和timer.html里的00:15不符,直接用15秒更准确。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.15 16:55:30