TM/GM 使用 MutationObserver 检查页面元素加载完成

这篇具有很好参考价值的文章主要介绍了TM/GM 使用 MutationObserver 检查页面元素加载完成。希望对大家有所帮助。如果存在错误或未考虑完全的地方,请大家不吝赐教,您也可以点击"举报违法"按钮提交疑问。

在 TamperMonkey 中经常需要在等待页面加载所有(或特定)元素后再去进行操作, 以前用的方法是通过 setTimeout 循环每隔一段时间检查一下 DOM 是否可以通过 document.querySelector 拿到. 下面分享使用原生的 MutationObserver 接口方式实现, 效率更高. MDN 介绍

The MutationObserver interface provides the ability to watch for changes being made to the DOM tree. It is designed as a replacement for the older Mutation Events feature, which was part of the DOM3 Events specification.

/**
 * Wait for an element before resolving a promise
 * @param {String} querySelector - Selector of element to wait for
 * @param {Integer} timeout - Milliseconds to wait before timing out, or 0 for no timeout              
 */
function waitForElement(querySelector, timeout) {
    return new Promise((resolve, reject) => {
        var timer = false;
        if (document.querySelectorAll(querySelector).length) return resolve();
        const observer = new MutationObserver(() => {
            if (document.querySelectorAll(querySelector).length) {
                observer.disconnect();
                if (timer !== false) clearTimeout(timer);
                return resolve();
            }
        });
        observer.observe(document.body, {
            childList: true,
            subtree: true
        });
        if (timeout) timer = setTimeout(() => {
            observer.disconnect();
            reject();
        }, timeout);
    });
}


// Use case
waitForElement(".cards-container", 10000).then(function () {
// ...
})

对于需要持续监测页面元素改变, 从而触发相应动作的场景, 参考下面写法:

// 定义监测触发的具体动作
const observer = new MutationObserver(changedNodes => {
    changedNodes.forEach(node => {
        console.log(node)
    })
});
// 开始监测整个 body 元素
observer.observe(document.body, {
    childList: true,
    subtree: true,
    attributes: true
});

这里监测的是所有 body 里面元素发生的所有变化, 如果有具体目标 DOM 也可以缩小监测的范围. 另外这里的动作只是将 changedNodes 即发生变化的节点在控制台进行输出.

MutationObserver() 构造函数接受的是一个 callback 回调函数 MDN 文档, 回调函数中处理的对象是一个 MutationRecord 类型的数组, 对应代码中我写的 changedNodes, 关于 MutationRecord 类型的属性:

  • MutationRecord.addedNodes
    The nodes added by a mutation. Will be an empty NodeList if no nodes were added.

  • MutationRecord.attributeName
    The name of the changed attribute as a string, or null.

  • MutationRecord.removedNodes
    The nodes removed by a mutation. Will be an empty NodeList if no nodes were removed.

  • MutationRecord.oldValue
    The value depends on the MutationRecord.type:

    • For attributes, it is the value of the changed attribute before the change.
    • For characterData, it is the data of the changed node before the change.
    • For childList, it is null.
  • MutationRecord.target
    The node the mutation affected, depending on the MutationRecord.type.

    • For attributes, it is the element whose attribute changed.
    • For characterData, it is the CharacterData node.
    • For childList, it is the node whose children changed.

举个栗子

百度首页的热搜是一个异步加载的列表, 用 MutationObserver 实现对热搜列表的实时监测, 如果内容发生改变的时候打印到 Console.

先确定热搜对应 DOM 的特征, 是放在一个 .hot-news-wrapper 类的 <div></div> 中.

在 Console 中使用这个类名进行选择测试

document.querySelectorAll('.hot-news-wrapper')

观察结果列表中只有一个对象, 确定可以直接用这个类名来定位目标 DOM
TM/GM 使用 MutationObserver 检查页面元素加载完成,前端开发,前端,javascript
在百度首页创建新的 TM 脚本:

// ==UserScript==
// @name         Dev-Mutation-test
// @namespace    http://tampermonkey.net/
// @version      0.1
// @description  try to take over the world!
// @author       You
// @match        https://www.baidu.com/
// @icon         https://www.google.com/s2/favicons?sz=64&domain=baidu.com
// @grant        none
// ==/UserScript==

const observer = new MutationObserver(changedNodes => {
    Array.from(changedNodes).forEach(node => {
        console.log(node)
    })
})

observer.observe(document.querySelector('.hot-news-wrapper'), {
    childList: true,
    subtree: true,
    attributes: true
})

刷新页面, 清空 Console 后点 换一换 观察实时输出的结果:

TM/GM 使用 MutationObserver 检查页面元素加载完成,前端开发,前端,javascript文章来源地址https://www.toymoban.com/news/detail-731180.html

到了这里,关于TM/GM 使用 MutationObserver 检查页面元素加载完成的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处: 如若内容造成侵权/违法违规/事实不符,请点击违法举报进行投诉反馈,一经查实,立即删除!

领支付宝红包 赞助服务器费用

相关文章

  • 【JavaScript】案例1:使用JS完成注册页面校验

    🔎这里是【JavaScript】,关注我学习前端不迷路 👍如果对你有帮助,给博主一个免费的点赞以示鼓励 欢迎各位🔎点赞👍评论收藏⭐️ 【JavaScript】 目前主要更新JavaScript,一起学习一起进步。 本期主要介绍案例1:使用JS完成注册页面校验 1. 需求说明 2. 知识讲解-JavaScript(

    2024年02月06日
    浏览(35)
  • Vue3学习(十九) - 使用Vue完成页面参数传递

    我知道自己现在的状态很不好,以为放个假能好好放松下心情,结果昨晚做梦还在工作,调试代码,和领导汇报工作。 天呐,明明是在放假,可大脑还在考虑工作的事,我的天那,这是怎么了? 1、任务拆解 页面跳转时带上当前电子书id参数ebookId 新增/编辑文档时,读取电子

    2024年03月09日
    浏览(36)
  • QT中资源文件resourcefile的使用,使用API完成页面布局

    在Qt中引入资源文件好处在于他能提高应用程序的部署效率并且减少一些错误的发生。 在程序编译过程中, 添加到资源文件中的文件也会以二进制的形式被打包到可执行程序中,这样这些资源就永远和可执行程序捆绑到一起了,不会出现加载资源却找不到的问题。 资源文件

    2024年02月12日
    浏览(31)
  • 使用selenium实现对页面元素的抓取

    工作中有个需求是需要对某个页面进行监控,但由于要监控页面数据是异步加载的,因此很难从状态码和返回结果层面进行校验。于是乎想到了通过判断页面元素是否存在且显示内容是否正确来达到此目标。调研了一下发现selenium可以实现对这种动态数据加载页面的抓取 备注

    2024年02月09日
    浏览(22)
  • [uniapp页面路由跳转]详细讲解uniapp中使用标签和的api完成页面跳转使用方法 代码注释

    Uniapp是一款基于Vue.js的跨平台开发框架,允许开发者使用同一套代码构建多个平台的应用程序,包括iOS、Android、Web、微信小程序、支付宝小程序、百度小程序、头条小程序等。在Uniapp中,页面跳转是非常重要的功能之一,本文将详细介绍Uniapp中页面跳转的各种标签和API的使用

    2024年02月20日
    浏览(38)
  • SpringMVC中使用引入jquery不能加载页面

    今天在学习springMVC的json数据绑定时,需要使用到jquery发送ajax请求。但是当我通过是script标签引入了jquery.js。 但是当我访问该jsp的时候就是不显示页面的内容 我一直以为时SpringMVC的servelt拦截器拦截了静态资源,但是我过滤了静态资源还是不显示。 后来才发现,我把script当作

    2023年04月09日
    浏览(32)
  • UE5 使用WebUI加载网页 页面黑屏

    0x00问题产生环境: Visual Studio2019 UE5 5.0.3 报错和截图如上,我是打包出来的exe在有些电脑上是没有问题的,有些电脑上出现这种情况。 0x01解决办法 如图修改: DefaultRHI选项 由Directx 12修改为Default即可 。(我的问题是通过这个解决的,希望对有需要的小伙伴们有帮助。) 0x02补

    2024年02月12日
    浏览(38)
  • 使用scrollTo/scrollTop让页面元素滚动到指定位置, 并设置滚动动画

    当容器有滚动条时,有时需要点击 试图 或 节点 将页面滚动到指定元素位置 比如父元素设置了 overflow: hidden; ,当元素里的内容超过元素本身的高度时, 就会出现滚动条, 那么鼠标滑动的距离就是其滚动距离. scrollTop属性 scrollTop 就是指 “元素中的内容” 超出 “元素上边界” 的

    2023年04月27日
    浏览(65)
  • iframe视频调用自适应页面大小使用css控制(同样适合其他元素)

    为了使iframe中的视频自适应页面大小,您可以使用CSS控制其宽度和高度。方便在电脑端和手机端等自适应显示大小,在实际项目还是比较常见呢,用CSS 不用再写JS来控制,这个是蛮不错呢。 首先,在HTML文件中,将iframe嵌入到一个包装元素(例如 )中,并为该包装元素分配一

    2024年02月11日
    浏览(31)
  • uniapp 中 的progress加载进度条 的使用,在 页面显示数据加载的进度条,使用户的使用体验效果更好

    学习目标如下: 例如: uniapp 中 的progress加载进度条 的使用,在 页面显示数据加载的进度条,使用户的使用体验效果更好 学习内容如下所示: 相关属性的说明 进度条的显示 是否显示属性的控制 显示进度条 进度条的样式设置 提示:这里统计学习计划的总量 1、进度条的显

    2024年02月15日
    浏览(43)

觉得文章有用就打赏一下文章作者

支付宝扫一扫打赏

博客赞助

微信扫一扫打赏

请作者喝杯咖啡吧~博客赞助

支付宝扫一扫领取红包,优惠每天领

二维码1

领取红包

二维码2

领红包