Javascript 通过chrome.tabs.sendMessage发送DOM节点对象
我正在写一个Chrome扩展。我需要将一个元素对象从内容脚本传递到背景脚本 目标:Javascript 通过chrome.tabs.sendMessage发送DOM节点对象,javascript,google-chrome,google-chrome-extension,Javascript,Google Chrome,Google Chrome Extension,我正在写一个Chrome扩展。我需要将一个元素对象从内容脚本传递到背景脚本 目标: 扩展是关于记录和重播用户操作。 数据保存在每个选项卡的不同对象上的扩展本地存储中(按选项卡ID)。 数据结构是{x:x,y:y,element:element} 当用户想要重播时,我对列表中的每个对象使用循环,并在元素上使用。单击() 内容脚本中的代码: 向后台脚本发送消息的函数: function addToEventHistory(cords) { console.log(cords) chr
扩展是关于记录和重播用户操作。
数据保存在每个选项卡的不同对象上的扩展本地存储中(按选项卡ID)。
数据结构是
{x:x,y:y,element:element}
当用户想要重播时,我对列表中的每个对象使用循环,并在元素上使用
。单击()
内容脚本中的代码:
向后台脚本发送消息的函数:
function addToEventHistory(cords) {
console.log(cords)
chrome.runtime.sendMessage({action: "addToEventHistory", cords: cords}, function(response) {
return response;
});
}
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();
获取元素并感测它的函数:
mouseClick: function(e) {
var target = e.target || e.srcElement
var clickEvent = {x: e.pageX, y: e.pageY, element: target}
addToEventHistory(clickEvent)
}
后台脚本中的代码:
function addToEventHistory(cords) {
console.log(cords)
chrome.runtime.sendMessage({action: "addToEventHistory", cords: cords}, function(response) {
return response;
});
}
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
。这些产出是:
发送:
对象{x:1205,y:1067,元素:div#content.snippet hidden}
接收:
Object{x:1205,y:1067,element:Object}
*元素对象为空,只有\u proto\u
原因是什么?
我如何解决这个问题
问题似乎不是序列化DOM对象,因为对象在发送前看起来正常,而在接收时看起来不正常。您不能将DOM元素作为消息发送
中的消息必须是“JSON ifiable对象”。DOM元素/节点不可JSON验证。因此,您不能发送它们。在您的情况下,您正试图发送单击事件的目标
您需要做什么而不是尝试序列化DOM元素,最终取决于您为什么在后台脚本中需要这些信息
如果要标识元素,则需要确定唯一的选择器。一种方法是为元素分配一个唯一的ID,并在消息中传递该ID。但是,只有当您希望在页面加载到该选项卡期间引用DOM节点时,这才有效。显然,一旦浏览器离开页面或将其加载到其他选项卡中,您分配的任何ID都将不可用。因此,该替代方案仅适用于在当前页面的生命周期内识别元素。但是,对于只想存储实际DOM元素的应用程序,分配唯一ID将是一个有效的解决方案。换句话说,存储DOM元素只在页面的生命周期内有效,因此分配唯一ID在相同的时间段(当前页面的生命周期)内有效
如果需要在重新加载页面时唯一标识元素的方法,您需要使用与分配ID不同的方法。使用什么在很大程度上取决于您希望使用元素时如何选择元素,以及您希望选择对页面结构中的更改具有多大的弹性(例如,在结构为动态的页面上,您可能需要使用静态页面以外的其他方法)
对于要录制和回放用户动作的应用程序,您需要根据鼠标在页面中的位置或用户启动事件的元素确定是否要录制这些动作。这是用于录制/回放/模拟用户动作的应用程序/语言的常见问题通常,用户可以选择如何记录此类用户交互(例如,通过位置或元素)。如果选择仅通过事件发生时的鼠标位置来存储用户操作,则可以使用来确定此时的元素并将事件发送到该元素。但是,执行此操作时,还需要跟踪文档的滚动状态并确定是否要存储该位置根据鼠标在当前显示中的位置或相对于文档的位置来设置鼠标的位置。不能将DOM元素作为消息发送
中的消息必须是“JSON ifiable对象”。DOM元素/节点不是JSON ifiable。因此,您无法发送它们。在您的情况下,您正在尝试发送单击事件的目标
您需要做什么而不是尝试序列化DOM元素,最终取决于您为什么在后台脚本中需要这些信息
如果要标识元素,则需要确定唯一的选择器。一种方法是为元素分配唯一的ID,并在消息中传递该ID。但是,只有在页面加载到该选项卡中期间要引用DOM节点时,该方法才有效。显然,您分配的任何ID都一旦浏览器离开页面或将其加载到其他选项卡中,该选项将不可用。因此,该选项仅适用于在当前页面的生命周期内标识元素。但是,对于只希望存储实际DOM元素的应用程序,分配唯一ID将是一个有效的解决方案。换句话说,storing DOM元素只在页面的生命周期内有效,因此分配唯一ID在相同的时间段(当前页面的生命周期)内有效
如果需要在重新加载页面时唯一标识元素的方法,则需要使用与分配ID不同的方法。使用什么在很大程度上取决于您希望使用元素时如何选择该元素,以及您希望选择对页面中的更改具有多大的弹性结构(例如,在结构为动态的页面上,您可能需要使用静态页面上无法使用的其他方法)
对于要录制和回放用户动作的应用程序,需要根据鼠标在t中的位置确定是否要录制这些动作