政务2.0

97 阅读5分钟

流程

- 流程梳理: [https://juejin.cn/editor/drafts/7368316813711556608](url)

难点一:iframe中页面执行时按钮的抓取

  • 因为项目结构比较复杂,进入页面后也有pageloadding很多页面相应影响的问题,所以这里就加了定时器一 直监听到相应改变,确保能抓到按钮的位置从而确保事件的执行
observeButtons(iframeDocument) {
const observer = new MutationObserver((mutations) => {
    const innerIframe = iframeDocument.getElementById("headerIframe");

    if (innerIframe) {
        innerIframe.onload = () => {
            const innerIframeDocument = innerIframe.contentDocument || innerIframe.contentWindow.document;
            const checkButtons = () => {
                const buttons = Array.from(innerIframeDocument.querySelectorAll("button"));
                buttons.forEach((button) => {
                    const buttonText = button.textContent.trim();
                    if (buttonText === "进入办事" && button.closest("#recept-footer-Notice")) {
                        button.addEventListener("click", () =>
                            this.handleButtonClick(buttonText, innerIframeDocument)
                        );
                        console.log("进入办事按钮事件监听器已添加。");
                        observer.disconnect(); // 断开 MutationObserver
                    } else if (buttonText === "确  定" && button.closest("#recept-footer-SceneGuide")) {
                        button.addEventListener("click", () =>
                            this.handleButtonClick(buttonText, innerIframeDocument)
                        );
                        console.log("确定按钮事件监听器已添加。");
                        observer.disconnect(); // 断开 MutationObserver
                    } else if (buttonText === "下一步" && button.closest("#recept-footer-Form")) {
                        button.addEventListener("click", () =>
                            this.handleButtonClick(buttonText, innerIframeDocument)
                        );
                        console.log("下一步按钮事件监听器已添加。");
                        observer.disconnect(); // 断开 MutationObserver
                    } else {
                        console.log("按钮未找到,继续检查...");
                    }
                });

                setTimeout(checkButtons, 500); // 每隔500ms检查一次
            };

            checkButtons();
        };
    } else {
        console.log("未找到内部 iframe,继续检查...");
    }
});

const config = { childList: true, subtree: true };
observer.observe(iframeDocument, config);
},
embedScriptInIframe() {
const iframe = this.$refs.aio_if;

// 等待 iframe 加载完成
iframe.onload = () => {
    const iframeDocument = iframe.contentDocument || iframe.contentWindow.document;

    // 创建一个 script 标签
    const script = iframeDocument.createElement("script");
    script.src = "https://oss-fsx.oss-cn-hangzhou.aliyuncs.com/terminal/inject.js"; // 确保路径正确
    script.type = "text/javascript";

    // 将 script 标签添加到 iframe 的 head 中
    iframeDocument.head.appendChild(script);

    // 验证脚本是否已加载
    script.onload = () => {
        console.log("global.js 已加载");
        callFlineJSAPI("init", "1", null, null);
        setTimeout(() => {
            this.observeButtons(iframeDocument);
            if (iframe.contentWindow.myGlobalFunction) {
                console.log("myGlobalFunction 已定义");
            } else {
                console.error("myGlobalFunction 未定义");
            }
        }, 1000); // 延迟检查,确保脚本完全执行
    };
    script.onerror = () => {
        console.error("global.js 加载失败");
    };
};
},

MutationObserver

MutationObserver是DOM Level 4规范中引入的一个功能,它提供了一种方式,可以监视DOM树中的变化,并作出相应的反应。这种变化可以是属性的变化、节点的添加或移除、文本内容的改变等。 以下是一个MutationObserver的基本使用示例:

  1. 创建MutationObserver实例: 首先,你需要创建一个MutationObserver的实例,并且传入一个回调函数,这个回调函数会在每次DOM发生变化时被调用。
  2. 配置观察选项: 然后,你需要定义一个配置对象,指定你想要观察的DOM变化类型,比如子节点的变化、属性的变化等。
  3. 开始观察: 使用observe方法,你可以开始观察一个特定的DOM节点。
  4. 处理变化: 当DOM发生变化时,MutationObserver会调用你提供的回调函数,并传入一个包含所有变化的MutationRecord对象的数组。
  5. 停止观察: 如果需要,你可以调用disconnect方法来停止观察。 下面是一个简单的例子,展示了如何使用MutationObserver来观察一个元素的内容变化:
// 创建MutationObserver实例
var observer = new MutationObserver(function(mutations) {
  mutations.forEach(function(mutation) {
    if (mutation.type === 'childList') {
      console.log('A child node has been added or removed.');
    } else if (mutation.type === 'attributes') {
      console.log('The ' + mutation.attributeName + ' attribute has been changed.');
    }
  });
});
// 配置观察选项
var config = { attributes: true, childList: true, subtree: true };
// 开始观察目标节点
var targetNode = document.getElementById('some-id');
observer.observe(targetNode, config);
// 停止观察
// observer.disconnect();

在这个例子中,我们创建了一个MutationObserver实例,并且配置了它来观察目标节点的子节点变化和属性变化。当这些变化发生时,控制台会打印出相应的信息。如果你想停止观察,可以调用observer.disconnect()MutationObserver是一个强大的工具,可以用于许多场景,比如实现自动化的单元测试、动态内容加载、无刷新页面更新等。

1. 自动化的单元测试

在自动化单元测试中,MutationObserver可以用来检测DOM是否按照预期发生了变化。

function simulateClick(element) {
  // 模拟点击事件
  var event = new MouseEvent('click', {
    'view': window,
    'bubbles': true,
    'cancelable': true
  });
  element.dispatchEvent(event);
}
function testDOMChange() {
  return new Promise(function(resolve, reject) {
    var observer = new MutationObserver(function(mutations) {
      mutations.forEach(function(mutation) {
        if (mutation.addedNodes.length) {
          // 检测到节点添加,假设这是期望的行为
          observer.disconnect();
          resolve();
        }
      });
    });
    var target = document.body;
    observer.observe(target, { childList: true });
    // 模拟用户行为,比如点击一个按钮
    var button = document.getElementById('my-button');
    simulateClick(button);
  });
}
// 使用测试框架的API来运行测试
test('DOM change on button click', function(assert) {
  return testDOMChange().then(function() {
    assert.ok(true, 'DOM changed as expected');
  });
});

在这个例子中,我们创建了一个MutationObserver来观察document.body的子节点变化。然后,我们模拟了一个点击事件,如果点击导致了期望的DOM变化(比如添加了新的节点),那么测试就会通过。

2. 动态内容加载

在动态内容加载中,MutationObserver可以用来检测何时新内容被添加到DOM中,并据此触发特定的逻辑。

function handleContentLoad(mutations) {
  mutations.forEach(function(mutation) {
    if (mutation.addedNodes.length) {
      // 新节点被添加,可以执行相关逻辑,比如初始化新添加的组件
      mutation.addedNodes.forEach(function(node) {
        if (node.tagName === 'DIV' && node.classList.contains('new-content')) {
          initializeNewContent(node);
        }
      });
    }
  });
}
var observer = new MutationObserver(handleContentLoad);
observer.observe(document.body, { childList: true, subtree: true });
function initializeNewContent(node) {
  // 初始化新内容的逻辑
  console.log('New content initialized:', node);
}

在这个例子中,我们设置了一个MutationObserver来观察整个文档树的子节点变化。当有新内容被添加到DOM中时,handleContentLoad函数会被调用,我们可以在这里初始化新添加的内容。

3. 无刷新页面更新

在无刷新页面更新(也称为SPA中的“页面切换”)中,MutationObserver可以用来检测页面部分的改变,并相应地更新页面状态。

function handlePageChange(mutations) {
  mutations.forEach(function(mutation) {
    if (mutation.type === 'childList') {
      // 检测到页面内容的改变,更新页面状态
      updatePageState();
    }
  });
}
var observer = new MutationObserver(handlePageChange);
var target = document.getElementById('page-content');
observer.observe(target, { childList: true });
function updatePageState() {
  // 更新页面状态的逻辑,比如更新URL、激活导航菜单等
  console.log('Page state updated.');
}

在这个例子中,我们创建了一个MutationObserver来观察ID为page-content的元素。当这个元素的子节点发生变化时,我们假设页面内容已经更新,然后调用updatePageState函数来更新页面的状态。 这些例子展示了MutationObserver在不同场景下的应用方式,它提供了一种灵活且强大的机制来响应DOM的变化。