如何将事件对象串起来

JSON.stringify(eventObject);

得到:

TypeError: Converting circular structure to JSON


dojox.json.ref.toJson(eventObject);

得到:

TypeError: Accessing selectionEnd on an input element that cannot have a selection.


是否有一些库/代码可以用来完成它?

您将无法使用JSON.stringify序列化事件对象,因为事件对象包含对DOM节点的引用,并且DOM在整个位置(例如,子/父关系)都有循环引用。 JSON不能处理这些默认情况下,所以你有点运气不好。

我build议看看如何序列化DOM节点为JSON,即使有循环引用? 对于如何序列化DOM节点有一些build议。 另外,以下问题似乎有用的信息:

  • 如何用循环引用保存对象?
  • 将具有循环引用的JavaScript对象string化(转换为JSON)

能够处理循环引用的JSON库似乎是

  • JSON-js(请参阅cycle.js)
  • dojox.json.ref

或者,如果不需要它们,则可以删除对DOM节点的所有引用,然后序列化该对象。 毕竟你不应该这样做。 请参阅@PointedEars评论:)

使用“替代品”function来避免错误:

 JSON.stringify(evt, function(k, v) { if (v instanceof Node) { return 'Node'; } if (v instanceof Window) { return 'Window'; } return v; }, ' '); 

不知道是否有帮助,但我只是在Angular JS文档中偶然发现了这一点:

*资料来源: https : //code.angularjs.org/1.5.5/docs/guide/expression#-event-

 /* * return a copy of an object with only non-object keys * we need this to avoid circular references */ function simpleKeys (original) { return Object.keys(original).reduce(function (obj, key) { obj[key] = typeof original[key] === 'object' ? '{ ... }' : original[key]; return obj; }, {}); } 

现在你可以做一些事情:

 JSON.stringify(simpleKeys(eventObject)); 

我有一个类似的问题,并写了一个简单的事件序列化与辅助方法来清理事件的path属性。 该解决scheme将数据从事件转换为可序列化对象的方法:

  • 复制原始属性
  • 为事件对象中的元素属性复制outerHTML
  • 计算path属性的select器path(这样可以避免复制整个HTML页面的outerHTML)
 // Calculate a string representation of a node's DOM path. var pathToSelector = function(node) { if (!node || !node.outerHTML) { return null; } var path; while (node.parentElement) { var name = node.localName; if (!name) break; name = name.toLowerCase(); var parent = node.parentElement; var domSiblings = []; if (parent.children && parent.children.length > 0) { for (var i = 0; i < parent.children.length; i++) { var sibling = parent.children[i]; if (sibling.localName && sibling.localName.toLowerCase) { if (sibling.localName.toLowerCase() === name) { domSiblings.push(sibling); } } } } if (domSiblings.length > 1) { name += ':eq(' + domSiblings.indexOf(node) + ')'; } path = name + (path ? '>' + path : ''); node = parent; } return path; }; // Generate a JSON version of the event. var serializeEvent = function(e) { if (e) { var o = { eventName: e.toString(), altKey: e.altKey, bubbles: e.bubbles, button: e.button, buttons: e.buttons, cancelBubble: e.cancelBubble, cancelable: e.cancelable, clientX: e.clientX, clientY: e.clientY, composed: e.composed, ctrlKey: e.ctrlKey, currentTarget: e.currentTarget ? e.currentTarget.outerHTML : null, defaultPrevented: e.defaultPrevented, detail: e.detail, eventPhase: e.eventPhase, fromElement: e.fromElement ? e.fromElement.outerHTML : null, isTrusted: e.isTrusted, layerX: e.layerX, layerY: e.layerY, metaKey: e.metaKey, movementX: e.movementX, movementY: e.movementY, offsetX: e.offsetX, offsetY: e.offsetY, pageX: e.pageX, pageY: e.pageY, path: pathToSelector(e.path && e.path.length ? e.path[0] : null), relatedTarget: e.relatedTarget ? e.relatedTarget.outerHTML : null, returnValue: e.returnValue, screenX: e.screenX, screenY: e.screenY, shiftKey: e.shiftKey, sourceCapabilities: e.sourceCapabilities ? e.sourceCapabilities.toString() : null, target: e.target ? e.target.outerHTML : null, timeStamp: e.timeStamp, toElement: e.toElement ? e.toElement.outerHTML : null, type: e.type, view: e.view ? e.view.toString() : null, which: e.which, x: ex, y: ey }; console.log(JSON.stringify(o, null, 2)); } }; // Create a mock event for this example var evt = new MouseEvent("click", { bubbles: true, cancelable: true, view: window }); var cb = document.getElementById("clicker"); // Add a click listener cb.addEventListener("click", serializeEvent); // Fire the event cb.dispatchEvent(evt); 
 <div> <button id="clicker" /> JSONify my click! </div>