当前位置: 首页 > Web前端 > HTML

如何确认DOM被不明来源修改

时间:2023-04-03 01:07:50 HTML

方案背景在刀耕火种的jQuery时代,我们都是直接对DOM进行操作,但是我们经常面临一个问题:DOM被不明来源的操作修改。而且这种改动大多不是按照一条线的逻辑,而是角落里的事件监听,或者没有关键词的AOE操作,非常难排错。在Vue时代,这种情况已经改善了很多,但是如果有人随便写ref或者随便用Watch,还是会遇到类似的问题。那么我们应该如何排查此类问题呢?核心思想浏览器其实有一个API可以监听DOM的任何变化:MutationObserver,无论是DOM上的属性还是它内部的子元素,都可以监听到所有的变化。但是不知道为什么这个东西一直没有得到全面的推广。Vue的$nextTick之前底层就是用这个API,后来被Promise取代了,但这并不影响我们使用它。有了MutationObserver,我们可以使用它在目标DOM的更改事件中设置调试器。当然这个注册动作至少要早于未知操作,然后可以通过Chrome的CallStack逐步找到操作的来源。这个方案的具体实现是尽可能设计成插件化的逻辑,操作都在控制台。代替代码中的全局声明,以MutationObserver为核心的调试器工具方法,需要将Vue项目显示挂载到窗口上//找不到DOM的情况专用调试器工具//谁在操作//调试器卡死后,可以从task开始栈,看看上层是谁导致的//观察到变化时执行的回调函数constcallback=function(mutationsList,observer){debugger;};//创建观察者实例并传入回调函数constobserver=newMutationObserver(callback);//通过上面的配置开始观察目标节点observer.observe(dom,config);}//全局挂载是为了我们在控制台进行操作window.listenerMutationObserver=listenerMutationObserver;尽早传递目标DOMa。在Vue项目中可以选择第一行mounted,在jQuery项目中可以选择DOM第一行Ready回调b。如果不想在代码中修改,可以直接在上面的位置设置断点,然后在控制台传入目标DOM//执行window.listenerMutationObserver(document.getElementById('test'))C。如果目标DOM没有明显的捕获标志,则在断点卡住后通过控制台动态发送D给DOM设置为d。如果不想在代码中写调试器,又在Sources中找不到自己想卡的代码文件,可以考虑从接口的源入手,让调试器卡在未知的地方DOM操作,并通过CallStark确认可疑的frameVue中的栈会比较多,而且由于在观察者队列中,很难直接观察到各个Watch,但至少可以找到问题的根源改变。如果是jQuery项目,在CallStack里会很直观