TypeError: Converting circular structure to JSON

2588 ワード

エラー:
[Vue warn]: Error in nextTick: "TypeError: Converting circular structure to JSON
    --> starting at object with constructor 'Vue'
    |     property '$options' -> object with constructor 'Object'
    |     property 'router' -> object with constructor 'VueRouter'
    --- property 'app' closes the circle"

解析:
一般的なエラーTypeError: Converting circular structure to JSONは、ループ参照が存在し、JSON.stringify法を用いて文字列に変換されるためである.簡単な例を示します.
  • エラーコード
    const x = { a: 8 };
    const b = { x };
    b.y = b; //     
    JSON.stringify(b); //     
    
  • 解決
    const x = { a: 8 };
    const b = { x };
    b.y = JSON.parse(JSON.stringify(b)); //      ,       ,      
    JSON.stringify(b);
    
    深コピーを使用することなく、ループ参照のコードを直接削除することもでき、問題の鍵はループ参照
  • を解除することである.
  • 本のブログのエラー位置は、ループリファレンスを明示的に見ることができません.ループリファレンスのコードは自分で書いたものではなく、フレームワークコードが自分で実現したものなので、問題の発生箇所を発見するのはもっと難しいです.午後ごろになって頭が爆発しそうになり、やっと夜明けの曙光が見えた.問題の原因を発見:
  • vuexのステータス管理stateには、routerのインスタンス(コンポーネントで取得するthis.$route)が格納、循環参照
  • が存在する.
  • vuexプラグインvuex-persistedstate
  • が使用する.stateには循環参照があり、プラグインvuex-persistedstateJSON.stringifyを実行してstateのデータを文字列に変換してブラウザのローカルストレージに格納する.次に、ループリファレンスを解除し、コンポーネントで取得したthis.$routeを深くコピーしてstateに格納する方法が解決される.
    /**
     *       
     * @param {All} [o]        
     * @returns {String}
     */
    export function getType(o){
      return Object.prototype.toString.call(o).slice(8,-1);
    }
    
    /**
     *            
     * @param {All} [o]        
     * @param {String} [type]     
     * @returns {Boolean}
     */
    export function isKeyType(o, type) {
    	return getType(o).toLowerCase() === type.toLowerCase();
    }
    
    /**
     *    ,       object Date Array     
     * @param {Any} sth
     * @return {Any}
     */
    export function deepClone(sth) {
      let copy;
      if (null == sth || "object" != typeof sth) return sth;
      if (isKeyType(sth, 'date')) {
        copy = new Date();
        copy.setTime(sth.getTime());
        return copy;
      }
      if (isKeyType(sth, 'array')) {
        copy = [];
        for (let i = 0, len = sth.length; i < len; i++) {
          copy[i] = deepClone(sth[i]);
        }
        return copy;
      }
      if (isKeyType(sth, 'object')) {
        copy = {};
        for (let attr in sth) {
          if (sth.hasOwnProperty(attr)) copy[attr] = deepClone(sth[attr]);
        }
        return copy;
      }
      return null;
    }
    
    ソースコードを深くコピーこのプロジェクトには、多くのフロントエンド共通の方法が含まれています.