通过chrome.tabs.sendMessage

时间:2016-10-15 17:50:10

标签: javascript google-chrome google-chrome-extension

我正在撰写Chrome扩展程序。我需要将元素对象从内容脚本传递给后台脚本。

目标:
扩展是关于记录和重播用户操作 数据保存在每个选项卡的不同对象的扩展名localstorage上(按选项卡ID) 数据结构是{x: x, y:y, element: element}的列表 当用户想要重放时,我为列表中的每个对象使用循环并在元素上使用.click()

内容脚本中的代码:

将消息发送到后台脚本的函数:

function addToEventHistory(cords) {
    console.log(cords)
    chrome.runtime.sendMessage({action: "addToEventHistory", cords: cords}, function(response) {
        return response;
    });
}

获取元素并感知它的函数:

mouseClick: function(e) {
                var target = e.target || e.srcElement
                var clickEvent = {x: e.pageX, y: e.pageY, element: target}
                addToEventHistory(clickEvent)
            }

后台脚本中的代码:

var tabId = sender.tab.id;
var existingRecords = JSON.parse(localStorage.getItem('record_'+tabId)) || [];
existingRecords.push(request.cords)
console.log(request.cords)
localStorage.setItem('record_'+tabId, JSON.stringify(existingRecords));
sendResponse();

问题是我发送的元素被收到一个空对象。发送和接收通知console.log。产出是:

发送:

Object {x: 1205, y: 1067, element: div#content.snippet-hidden}

接收:

Object {x: 1205, y: 1067, element: Object}

*元素Object为空且只有_proto_

是什么原因?
我该如何解决这个问题?

看起来问题不是序列化DOM对象,因为对象在发送之前看起来没问题,而且在接收时不正常..

2 个答案:

答案 0 :(得分:3)

您无法将DOM元素作为runtime.sendMessage()消息发送

runtime.sendMessage()中的消息必须是“JSON-ifiable对象”。 DOM元素/节点不是JSON-ifiable。因此,你不能发送它们。在您的情况下,您尝试发送target事件的click

您需要做的而不是尝试序列化DOM元素最终取决于您在后台脚本中需要此信息的原因。

如果要识别元素,则需要确定唯一的选择器。一种方法是为元素分配一个唯一的ID,并在您的消息中传递该ID。但是,只有在页面加载到该选项卡期间要引用DOM节点时,这才有效。显然,一旦浏览器离开页面,或者将其加载到不同的选项卡中,您分配的任何ID都将不可用。因此,该替代方案仅对于识别当前页面的生命周期的元素是可行的。但是,对于您只想存储实际DOM元素的应用程序,分配唯一ID将是一种有效的解决方案。换句话说,存储DOM元素仅对页面的生命周期有效,因此分配唯一ID将在同一时间段(当前页面的生命周期)内有效。

如果您想要在重新加载页面时唯一标识元素的方法,则需要使用与分配ID不同的方法。使用什么在很大程度上取决于您在想要使用它时如何选择元素以及您希望选择与页面结构的变化相关的弹性(例如,在结构是动态的页面上,您可能需要使用其他方法而不是在静态页面上工作。)

对于您要记录和回放用户操作的应用程序,您需要根据鼠标在页面中的位置或根据用户启动事件的元素来确定是否要记录这些操作。这是用于记录/回放/模拟用户操作的应用程序/语言的常见问题。通常,用户可以选择如何记录这种用户交互(例如,通过位置或元素)。如果您选择仅在事件发生时通过鼠标的位置存储用户操作,那么您可以使用Document.elementFromPoint()来确定当前现在哪个元素并发送该元素的事件。但是,在执行此操作时,您还需要跟踪文档的滚动状态,并根据鼠标在当前显示中的位置或相对于文档来确定是否要存储鼠标的位置。 / p>

答案 1 :(得分:1)

我使用了一种解决方法来点击元素

除了保存元素然后使用element.click()我还使用了线来点击元素而不保存元素本身:

document.elementFromPoint(cords.x - window.pageXOffset, cords.y - window.pageYOffset).click();