zoenbo 发表于 2023-6-7 17:45:50

大佬帮我看一下DOM节点被删除的问题

本帖最后由 zoenbo 于 2023-6-7 17:46 编辑

我想让所有加载出来的DOM元素节点不要因为向下滚动而被删除,
当翻到8页的时候第一个.page下的.canvasWrapper和.textLayer会被删除,
.page的行内属性data-loaded="true"也会跟着删除掉,
被<div class="loadingIcon notVisible" role="img" aria-label="正在载入…"></div>这个所代替了~
下边的脚本只能保持.canvasWrapper和.textLayer不被删除,
但不是我要的最终效果,
我想让所有已加载的.page和节点原封不动的保留(不要loadingIcon notVisible出现,也不要让data-loaded="true"消失),

总之要的结果就是不管下翻多少页,往上翻时不用重新加载~

大佬帮帮忙,帮我修改下,我实在是解决不了了~
(改JS的方法会,想用脚本来实现)

@李恒道

页面:http://biaozhun.osta.org.cn/pdfview.html?code=597

```
// ==UserScript==
// @name         Block Node Operations
// @namespace    YOU   
// @version      1
// @descriptionBlock operations on specific nodes in a web page
// @match      http://biaozhun.osta.org.cn/pdfview.html?code=*
// @grant      none
// ==/UserScript==

(function() {
    'use strict';

    const observer = new MutationObserver(mutations => {
      for (const mutation of mutations) {
            if (mutation.type === 'attributes' && mutation.attributeName === 'data-loaded') {
                const page = mutation.target.closest('.page');
                if (page && !page.getAttribute('data-loaded')) {
                  console.log("Setting data-loaded attribute to true for .page element");
                  page.setAttribute('data-loaded', 'true');
                }
            }
      }
    });

    observer.observe(document.body, { childList: true, subtree: true });

    const originRemove = HTMLDivElement.prototype.remove;
    const originRemoveChild = HTMLDivElement.prototype.removeChild;

    Object.defineProperty(HTMLDivElement.prototype, 'remove', {
      value: function () {
            if ((this.classList.contains("canvasWrapper") || this.classList.contains("textLayer")) && !this.closest('.page')) {
                console.log("Rejected remove", this);
                return;
            } else {
                originRemove.apply(this, arguments);
            }
      },
      configurable: true,
      enumerable: true,
      writable: true,
    });

    Object.defineProperty(HTMLDivElement.prototype, 'removeChild', {
      value: function (element) {
            if ((element.classList.contains("canvasWrapper") || element.classList.contains("textLayer")) && !element.closest('.page')) {
                console.log("Rejected removeChild", element);
                return;
            } else {
                originRemoveChild.apply(this, arguments);
            }
      },
      configurable: true,
      enumerable: true,
      writable: true,
    });
})();
```

zoenbo 发表于 2023-6-7 18:30:31

@李恒道 有请大佬~

李恒道 发表于 2023-6-7 18:50:22

mutationObeserve是监听改变
在触发事件的时候已经被删除了
可以考虑用 EventTarget上的remove劫持判断this阻止删除
const oldRemove=Element.prototype.remove

Element.prototype.remove=function (...args){
   console.log('this,...args',this,...args)
    if(this.className==='textLayer'||this.className==='canvasWrapper'){
      return;
    }
    return oldRemove.call(this,...args)
}
但是如果即使解除了dom,网页中的实例已经销毁,实际二次依然会重新渲染
这个时候只能尝试去研究销毁的机制
首先打dom销毁断点,堆栈回溯找到
_createClass(PDFPageViewBuffer, [{
    key: "push",
    value: function push(view) {
      var buf = _classPrivateFieldGet(this, _buf);

      if (buf.has(view)) {
      buf["delete"](view);
      }

      buf.add(view);

      if (buf.size > _classPrivateFieldGet(this, _size)) {
      _classPrivateMethodGet(this, _destroyFirstView, _destroyFirstView2).call(this);
      }
    }
}
这里可以看到每次push循环判断大小,然后触发销毁
_classPrivateMethodGet(this, _destroyFirstView, _destroyFirstView2).call(this);
那我们核心思路就变成了劫持push
是通过_createClass调用的
看_createClass
function _defineProperties(target, props) { for (var i = 0; i < props.length; i++) { var descriptor = props; descriptor.enumerable = descriptor.enumerable || false; descriptor.configurable = true; if ("value" in descriptor) descriptor.writable = true; Object.defineProperty(target, descriptor.key, descriptor); } }

function _createClass(Constructor, protoProps, staticProps) { if (protoProps) _defineProperties(Constructor.prototype, protoProps); if (staticProps) _defineProperties(Constructor, staticProps); Object.defineProperty(Constructor, "prototype", { writable: false }); return Constructor; }

可以看到是原型挂载
所以直接打印PDFPageViewBuffer.prototype.push即可触发到push
劫持push再通过函数拿大小/修改size/修改函数等等即可实现操作
这部分就留给你做课后作业了

zoenbo 发表于 2023-6-7 18:59:11

李恒道 发表于 2023-6-7 18:50
mutationObeserve是监听改变
在触发事件的时候已经被删除了
可以考虑用 EventTarget上的remove劫持判断this ...

大佬威武,让我学到了新思路~超级感谢~

脚本体验师001 发表于 2023-6-7 21:46:13

zoenbo 发表于 2023-6-7 18:59
大佬威武,让我学到了新思路~超级感谢~

哥哥这是要做啥脚本?我看各种方法都用上了,必定不一般,啥时候能做好给咱们瞧瞧

zoenbo 发表于 2023-6-7 22:26:17

脚本体验师001 发表于 2023-6-7 21:46
哥哥这是要做啥脚本?我看各种方法都用上了,必定不一般,啥时候能做好给咱们瞧瞧 ...

这个就是网上看书的,一翻页之前的内容就消失重新加载,所以想解决这个问题,个别网站有加密不用调试代码...菜鸟的笨办法{:4_108:}
页: [1]
查看完整版本: 大佬帮我看一下DOM节点被删除的问题