首页 > 解决方案 > 将 devtools 中当前选定的元素传递给电子中的 javascript

问题描述

我想让用户通过电子中的 devtools 选择一个 html 元素。我知道您可以使用变量 $0 来获得它。问题是它只能在开发工具控制台中访问。

我查看了 Chrome DevTools 协议,发现 Runtime.evaluate 有一个包含命令行 api 的参数。这似乎适用于除 $0 之外的所有内容。我可以调用 clear()、$() 和其他东西。但是 $0 是未定义的。

let debug = mainWindow.webContents.debugger;
debug.attach();

mainWindow.webContents.on("devtools-opened", () => {
    devToolsOpen = true;
    myEmitter.emit("devtoolsready");
});

mainWindow.webContents.on("devtools-closed", () => {
    devToolsOpen = false;
});

//coords from renderer mouse event
ipcMain.on("inspectelement", (event, pageX, pageY) => {
    mainWindow.webContents.inspectElement(pageX, pageY);
    //if the devtools are not ready yet, wait for the event before executing the function
    if (devToolsOpen === false) {
        myEmitter.once("devtoolsready", devToolsFunction)
    }
    else {
        devToolsFunction();
    }

    async function devToolsFunction() {

        let backendNodeId = (await debug.sendCommand("DOM.getNodeForLocation", { x: pageX, y: pageY })).backendNodeId;
        let resolvedNode = (await debug.sendCommand("DOM.resolveNode", { backendNodeId: backendNodeId }));
        let js$0False = (await debug.sendCommand("Runtime.evaluate", { expression: "alert($0)", includeCommandLineAPI: false }));
        let js$0True = (await debug.sendCommand("Runtime.evaluate", { expression: "alert($0)", includeCommandLineAPI: true }));

        console.log(backendNodeId);
        console.log(resolvedNode);
        //Fails because $0 is not defined, does not alert
        console.log(js$0False);
        //$0 is set to undefined
        console.log(js$0True);
    }
});

我还尝试使用 Dom.getNodeForLocation 通过内部 dom 表示来获取元素,但我不知道应该如何使用它来获取实际元素。

$0 未定义对我来说似乎是一个错误,但我不确定。

标签: electron

解决方案


经过一些更多的实验,似乎 devtools 和 devtools 协议不共享 0 美元。解决方法是将选定的节点推送到前端,然后调用 setInspectedNode。在此之后,变量将被设置和访问。

//required for subsequent calls. Not sure if it is needed for every call but maybe 
//it does not update automaticly so it stays here
let doc = (await debug.sendCommand("DOM.getDocument"));

//backend id of the node at mouse position
let backendNodeId = (await debug.sendCommand("DOM.getNodeForLocation", { x: pageX, y: pageY })).backendNodeId;

//needed to push the backend node to the fron
let front = (await debug.sendCommand("DOM.pushNodesByBackendIdsToFrontend", { backendNodeIds: [backendNodeId] }));

//it seems like the devtools context and this one do not share $0.
//Because of this you need to call setInspectedNode, after which it will be set and accessible
let inspect = (await debug.sendCommand("DOM.setInspectedNode", { nodeId: front.nodeIds[0] }));

//write $0 to another var accessable from a normal js context
let js$0True = (await debug.sendCommand("Runtime.evaluate", { expression: "selectedNode = $0", includeCommandLineAPI: true }));

推荐阅读