40

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.


それを達成するためにすぐに使用できるライブラリ/コードはありますか?

4

7 に答える 7

21

JSON.stringify を使用してイベント オブジェクトをシリアル化することはできません。これは、イベント オブジェクトに DOM ノードへの参照が含まれており、DOM のいたるところに循環参照 (子/親の関係など) があるためです。JSON はデフォルトではこれらを処理できないため、少し運が悪いです。

循環参照がある場合でも、DOM ノードを JSON にシリアル化する方法を確認することをお勧めしますか? これには、DOM ノードをシリアライズする方法に関するいくつかの提案があります。また、次の質問には有用な情報があるようです。

循環参照を処理できるJSONライブラリは

または、DOM ノードへの参照が不要な場合はすべて削除してから、オブジェクトをシリアル化することもできます。結局のところ、これを行うべきではありません。@PointedEarsのコメントを参照してください:)

于 2012-07-18T18:20:11.610 に答える
6

同様の問題があり、イベントのパス属性をクリーンアップするヘルパー メソッドを使用して単純なイベント シリアライザーを作成しました。イベントからシリアライズ可能なオブジェクトにデータを変換するこのソリューションのアプローチ:

  • プリミティブ アトリビュートをコピー
  • イベント オブジェクトの要素属性の outerHTML をコピーします。
  • 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: e.x,
      y: e.y
    };

    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>

于 2017-02-16T20:59:20.507 に答える
1

それが役立つかどうかはわかりませんが、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));
于 2014-06-11T11:17:54.223 に答える