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

Tampermonkey脚本:文档加载与分页点击时函数无法执行问题排查

解决Tampermonkey脚本触发时机与动态内容处理问题

问题背景

我正在编写Tampermonkey脚本扩展日常使用的业务Web应用,需求为提取页面中特定URL内的数字,并用该数字构建新链接追加到对应父元素中。

当前脚本存在以下问题:

  • 文档加载完成时触发函数无效
  • 点击类名为pagination-sm的UL分页元素时触发函数无效
  • 仅点击文档任意位置时函数可正常运行

推测原因:

  • 页面实际数据加载滞后于JS文档加载事件触发时机
  • 分页切换时动态生成新链接,原有绑定逻辑无法触发函数重新处理新内容

当前脚本代码

(function() {
    'use strict';

    //get the pagination element
    var element = document.getElementsByClassName('pagination-sm');
    element.onclick = createLinks;
    document.onload = createLinks;

    function createLinks() {
    var links = document.querySelectorAll ("a[href*='/Field/POPendingCreate/']");

        for (var J = links.length-1; J >= 0; --J) {
            var thisLink = links[J];
            console.log(thisLink.href);
            var ppon = thisLink.href.match(/\d+/)[0];
            console.log(ppon);

            var a = document.createElement('a');
            var linkText = document.createTextNode("Preview Order");
            a.appendChild(linkText);
            a.title = "Preview Order";
            a.href = "https://website.com/Field/DownloadPendingPO?POPPKeyID=" + ppon + "&co=1&po=" + ppon;
            a.target = "_blank";

            var parentNode = thisLink.parentNode;
            console.log(parentNode);
            parentNode.appendChild(a);

        }
    }

 })();

分页元素结构

<ul uib-pagination="" items-per-page="formData.itemPerPage" class="pagination-sm ng-pristine ng-untouched ng-valid ng-scope ng-isolate-scope pagination ng-not-empty" data-total-items="pendingList.length" data-ng-model="formData.currentPage" data-max-size="10" data-ng-if="!attachmentView && filteredDocuments.length > 0" role="menu">
<!-- ngIf: ::boundaryLinks -->
<!-- ngIf: ::directionLinks -->
<li role="menuitem" ng-if="::directionLinks" ng-class="{disabled: noPrevious()||ngDisabled}" class="pagination-prev ng-scope disabled">
<a href="" ng-click="selectPage(page - 1, $event)" ng-disabled="noPrevious()||ngDisabled" uib-tabindex-toggle="" class="ng-binding" disabled="disabled" tabindex="-1">Previous</a>
</li>
<!-- end ngIf: ::directionLinks -->
<!-- ngRepeat: page in pages track by $index -->
<li role="menuitem" ng-repeat="page in pages track by $index" ng-class="{active: page.active,disabled: ngDisabled&&!page.active}" class="pagination-page ng-scope active">
<a href="" ng-click="selectPage(page.number, $event)" ng-disabled="ngDisabled&&!page.active" uib-tabindex-toggle="" class="ng-binding">1</a>
</li>
<!-- end ngRepeat: page in pages track by $index -->
<!-- ngIf: ::directionLinks -->
<li role="menuitem" ng-if="::directionLinks" ng-class="{disabled: noNext()||ngDisabled}" class="pagination-next ng-scope disabled">
<a href="" ng-click="selectPage(page + 1, $event)" ng-disabled="noNext()||ngDisabled" uib-tabindex-toggle="" class="ng-binding" disabled="disabled" tabindex="-1">Next</a>
</li>
<!-- end ngIf: ::directionLinks -->
<!-- ngIf: ::boundaryLinks -->
</ul>

解决方案与修正脚本

核心问题分析

  1. 元素绑定错误:getElementsByClassName返回HTMLCollection类数组,直接赋值onclick无效,需定位到具体元素。
  2. 加载事件错误:document.onload不是标准加载事件,且无法覆盖异步加载的动态内容。
  3. 动态内容未监听:分页切换由Angular生成DOM,直接绑定点击事件会因元素动态更新失效,需用事件委托或MutationObserver监听内容变化。

修正后的脚本

(function() {
    'use strict';

    // 初始化:页面加载后先执行一次
    window.addEventListener('load', init);

    function init() {
        createLinks();
        setupEventDelegation();
        setupMutationObserver();
    }

    // 事件委托:监听分页点击(兼容Angular动态生成的元素)
    function setupEventDelegation() {
        document.addEventListener('click', function(e) {
            // 判断点击目标是否属于分页元素
            if (e.target.closest('.pagination-sm')) {
                // 延迟执行,等待Angular更新DOM
                setTimeout(createLinks, 300);
            }
        });
    }

    // MutationObserver:监听动态加载的链接元素
    function setupMutationObserver() {
        // 替换为包含目标链接的父容器选择器(比如列表容器,找不到就用body)
        const targetNode = document.querySelector('body');
        if (!targetNode) return;

        const config = { childList: true, subtree: true };
        const observer = new MutationObserver(function(mutations) {
            // 检查是否有目标链接被添加
            if (document.querySelector("a[href*='/Field/POPendingCreate/']")) {
                createLinks();
            }
        });
        observer.observe(targetNode, config);
    }

    function createLinks() {
        const links = document.querySelectorAll("a[href*='/Field/POPendingCreate/']");
        
        links.forEach(link => {
            const parentNode = link.parentNode;
            // 避免重复添加链接
            if (parentNode.querySelector('.preview-order-link')) return;

            const pponMatch = link.href.match(/\d+/);
            if (!pponMatch) return;
            const ppon = pponMatch[0];

            const previewLink = document.createElement('a');
            previewLink.className = 'preview-order-link'; // 标记已处理
            previewLink.textContent = "Preview Order";
            previewLink.title = "Preview Order";
            previewLink.href = `https://website.com/Field/DownloadPendingPO?POPPKeyID=${ppon}&co=1&po=${ppon}`;
            previewLink.target = "_blank";
            
            // 可添加样式区分
            previewLink.style.marginLeft = '8px';
            
            parentNode.appendChild(previewLink);
        });
    }

})();

关键改进点

  • 事件委托:通过监听document的点击事件,判断点击源是否属于分页元素,避免直接绑定动态生成元素的点击事件失效。
  • MutationObserver:监听DOM树变化,当动态加载的目标链接出现时自动执行处理逻辑,覆盖异步加载场景。
  • 去重处理:给生成的预览链接添加类名标记,避免多次执行函数时重复创建链接。
  • 延迟执行:分页点击后延迟300ms执行,确保Angular完成DOM更新后再处理新内容。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.16 03:09:56