[油猴脚本开发指南] 元素等待器的简易方法
# 元素等待器的简易方法## 前言
元素等待器是什么? 现在网页基本都是基于框架去编写的, 那么 Dom 元素就并非直接写在 HTML 中的, 而是通过 JS 渲染出来的. 那么就会出现一个问题, 在 `load` / `DOMContentLoaded` 事件触发时, 网页上并非是完全的 HTML 结构, 还有一些元素仍然在异步载入中. 所以现在的脚本如果需要在页面载入时操作 Dom , 那么就需要通过一个元素等待器去等待元素载入后, 再进行后续的操作.
`MutationObserver` 是一个很好的解决方案, 但是有一个问题是, 写起来确实有点繁琐. 如果不是直接导入函数库/已经写好的函数, 那么手写的话会非常的麻烦. 只写一遍还好说, 但是如果每次都要写的话会很麻烦.
有时候想写一些简单的脚本, 不想开一个新的项目, 想直接在网页编辑器中编写代码, 又不想依赖第三方库的时候, 想要获取异步载入的元素怎么办呢? 最简单的方法: **轮询**.
> 第三库的异步元素等待器: (https://scriptcat.org/zh-CN/script-show-page/513) .
> (https://learn.scriptcat.org/%E5%AE%9E%E7%94%A8%E7%9F%A5%E8%AF%86%E5%BA%93/JavaScript%20%E7%9F%A5%E8%AF%86%E7%AF%87/MutationObserve%20%E7%9F%A5%E8%AF%86/)
## 粗暴延时
```js
// 函数入口
const main = () => {
const dom = document.querySelector( '#app' );
// any code
};
// 粗暴延时5s开始运行函数
setTimeout( main, 5_000 );
```
## 轮询
**轮询** 本质上是对于粗暴延时的简单优化, 因为延时不仅反应慢, 并且也有可能等待后元素仍然没有载入导致函数错误.
```js
// 函数入口
const main = () => {
// any code
};
// 每 500 ms 查询一次元素载入状态
const getterTimer = setInterval( () => {
const dom = document.querySelector( '#app' );
// 如果元素载入
if ( dom ) {
// 清除定时器
clearInterval( getterTimer );
// 运行函数
main();
}
}, 500 );
```
这样, 只需要一次定时器的开启和关闭操作, 就可以完成等待异步元素载入的操作. 在一些随便写写的简单脚本上, 会比手写 `MutationObserver` 会方便不少.
> 当然, 如果开一个项目写脚本, 能用 `MutationObserver` 还是优先选用 `MutationObserver` 去载入函数.
## 简单封装轮询
> 虽然 js/ts 主流的类型语法库还没有支持, 但是 `Promise.withResolvers()` 是已经在所有浏览器全面支持的, 是可以直接使用的.
```js
/**
* 获取异步载入的元素
*
* @parma {string} selector 元素选择器
* @parma {number} 轮询延时
*
* @Return {Promise<Element>} 载入的元素
* */
function elementGetter( selector, delayPerMs = 500 ) {
let { promise, resolve, reject } = Promise.withResolvers();
// 轮询获取元素载入情况
const getterTimer = setInterval( () => {
const dom = document.querySelector( '#app' );
// 如果元素载入
if ( dom ) {
// 清除定时器
clearInterval( getterTimer );
// 兑现 promise
resolve( dom );
}
}, delayPerMs );
// 返回 Promise
return promise;
}
```
那复杂方法是什么方案了? s11s 发表于 2024-7-12 23:20
那复杂方法是什么方案了?
可以看 (https://learn.scriptcat.org/%E5%AE%9E%E7%94%A8%E7%9F%A5%E8%AF%86%E5%BA%93/JavaScript%20%E7%9F%A5%E8%AF%86%E7%AF%87/MutationObserve%20%E7%9F%A5%E8%AF%86/) 这个链接里的内容. 也就是我说的 `MutationObserver` , 然后这里面有一个 **延迟查询代码范例解读** 章节, 这个章节里分析了一个函数, 就是一个利用 `MutationObserver` 实现元素等待器的函数. 《暴力美学》
页:
[1]