Vue親子コンポーネントのいくつかのピットの値を伝える


Vueの親子コンポーネントで値を伝える時に冷門の問題が発生し、サブアセンブリが値を変えた後、親のコンポーネントの値も変わってきました。ここで原因と解決方法を記録します。
システムを整理して、JavaScriptの深度コピーと浅いコピー関連の知識点を整理します。
1.問題の説明
親コンポーネントは、サブアセンブリに値を伝え、子アセンブリは、伝えられた値を変えると、親コンポーネントの値も変わる。
この問題は比較的に寒いです。普段はコンポーネント通信を簡単に使えば、普通は出会いません。
2.原因分析
  • コア:双方向バインディング
  • 親子コンポーネントが値を伝えるときは、双方向バインディングに関連し、値がobjectタイプの場合は、値を送るとデータソースが変化します。
  • ディープコピーと浅いコピー
  • 以下詳細に述べる。
    3.ソリューション
    私が現在採用している解決策は:
    値を送るときは、直接データソースを送らず、コピーや定義などで値を伝えます。
    簡単に処理するならJSON.parse(JSON.strigify(obj))ですが、このような簡単で粗暴な方法には限界があります。値がundefined、function、smbolは変換中に無視されます。したがって、オブジェクト値がこの3つあると、この方法で属性が失われます。
    残りは、深くコピーしたツール関数を書くか、直接に第三者のライブラリ関数を借りるか、次のように展開します。
    4.深いコピーと浅いコピー
    JavaScriptの中の浅いコピーと深いコピーは、複雑なデータタイプ(Object、Aray)のコピー問題に対してだけです。浅いコピーと深いコピーは、既存のオブジェクトに再生する役割を果たすことができます。しかし、対象の例は、スタックメモリに記憶されている後、一つの参照値を介してオブジェクトを操作することで、コピーする場合は、2つのケースがあります。引用とコピーの例をコピーする場合は、これも和深コピーの浅い違いです。
    下図はJavaScriptの複雑なデータタイプの浅いコピーの模式図です。
  • コピーが浅いです
  • コピーはコピー参照であり、コピー後の参照は同じオブジェクトを指す例であり、互いの動作は互いに影響し合う。
    注意すべきなのはObject.assigin()は浅いコピーで、それは第1層を深くコピーすることしかできなくて、深層のはまだ浅いコピーです。Object.assignのコピーは属性値ですから。ソースオブジェクトの属性値がオブジェクトの参照である場合は、その参照だけを指します。MDNから抜粋する
    MDNがassignを述べる時、典型的な例があります。ここは記事リンクです。
    以下に、最初のクラスの浅いコピー-元のオブジェクトの参照を列挙する。
    
    /**
     *       
     */
    var obj1 = {
     name:'wenyuan',
     age: 22
    }
    var obj2 = obj1;
    obj2['job'] = 'coder';
    console.log(obj1); //Object {name: "wenyuan", age: 22, job: "coder"}
    console.log(obj2); //Object {name: "wenyuan", age: 0, job: "coder"}
    
    
    /* -------------------------        ------------------------- */
    
    
    /**
     *       
     */
    var arr1 = [1, 2, 3, '4'];
    var arr2 = arr1;
    arr2[1] = "test"; 
    console.log(arr1); // [1, "test", 3, "4"]
    console.log(arr2); // [1, "test", 3, "4"]
    次に、第2のクラスの浅いコピー−ソースオブジェクトのコピー例を見て、その属性オブジェクトのコピー参照:
    この場合、外部ソースオブジェクトはコピーの例であり、その属性要素が複雑なデータタイプ(Object、Aray)の場合、内部要素は参照をコピーする。
    ソースオブジェクトに直接操作すると、他のオブジェクトに影響はありませんが、属性操作時には別のオブジェクトの属性の値が変わります。
    
    /**
     *       
     * jQuery  $.extend(a,b)   $.extend({},a,b)
     */
    var obj1 = {
     name:'wenyuan',
     age: 22,
     social: {
      blog: 'www.wenyuanblog.com'
     },
     skills: ['js', 'html', 'css', 'python']
    }
    var obj2 = $.extend({},obj1);
    console.log(obj1 === obj2) //   false,            
    console.log(obj1.social === obj2.social) //   true,    Object          
    console.log(obj1.skills === obj2.skills) //   true,    Array          
    
    
    /**
     *       
     * ES6  Object.assign()          ...
     */
    var obj1 = {
     name:'wenyuan',
     age: 22,
     social: {
      blog: 'www.wenyuanblog.com'
     },
     skills: ['js', 'html', 'css', 'python']
    }
    var obj2 = Object.assign({},obj1);
    console.log(obj1 === obj2) //   false,            
    console.log(obj1.social === obj2.social) //   true,    Object          
    console.log(obj1.skills === obj2.skills) //   true,    Array          
    var obj3 = {...obj1};
    console.log(obj1 === obj3) //   false,            
    console.log(obj1.skills === obj3.skills) //   true,    Array          
    console.log(obj1.skills === obj3.skills) //   true,    Array          
    
    
    /* -------------------------        ------------------------- */
    
    
    /**
     *       
     * Array.prototype.slice()
     */
    var arr1 = [{name: "wenyuan"}, {name: "Evan You"}];
    var arr2 = arr1.slice(0);
    console.log(arr1 === arr2); //   false,            
    console.log(arr1[0] === arr2[0]); //   true,           
    
    
    /**
     *       
     * Array.prototype.concat()
     */
    var arr1 = [{name: "wenyuan"}, {name: "Evan You"}];
    var arr2 = arr1.concat();
    console.log(arr1 === arr2); //   false,            
    console.log(arr1[0] === arr2[0]); //   true,           
    
    
    /**
     *       
     * ES6  Object.assign()          ...
     *           ,  ES6             
     */
    var arr1 = [{name: "wenyuan"}, {name: "Evan You"}];
    var arr2 = Object.assign([],arr1)
    var arr3 = { ...arr1 };
    console.log(arr1 === arr2); //   false,            
    console.log(arr1 === arr3); //   false,            
    console.log(arr1[0] === arr2[0]); //   true,           
    console.log(arr1[0] === arr3[0]); //   true,           
  • コピー
  • メモリをヒープに再割り当てし、ソースオブジェクトのすべての属性を新規にコピーし、深くコピーしたオブジェクトの参照図には元のオブジェクトまたは対象図のいずれのオブジェクトも含まれていないことを保証し、コピーしたオブジェクトと元のオブジェクトは完全に分離されており、互いに影響がない。
    いくつかの深いコピーの例を挙げます。
    
    /**
     *       
     * JSON.stringify() JSON.parse()
     *         ,      ,        
     */
    var obj1 = {
     name:'wenyuan',
     age: 22,
     social: {
      blog: 'www.wenyuanblog.com'
     },
     skills: ['js', 'html', 'css', 'python']
    }
    var obj2 = JSON.parse(JSON.stringify(obj1));
    console.log(obj1 === obj2) //   false,            
    console.log(obj1.social === obj2.social) //   false,    Object           
    console.log(obj1.skills === obj2.skills) //   false,    Array           
    
    
    /**
     *       
     * jQuery  $.extend(true,a,b)
     */
    var obj1 = {
     name:'wenyuan',
     age: 22,
     social: {
      blog: 'www.wenyuanblog.com'
     },
     skills: ['js', 'html', 'css', 'python']
    }
    var obj2 = $.extend(true,obj1);
    console.log(obj1 === obj2) //   false,            
    console.log(obj1.social === obj2.social) //   false,    Object           
    console.log(obj1.skills === obj2.skills) //   false,    Array           
    
    
    /**
     *       
     *             ,   +  ,          
     *       ,                  ,          
     */
    
    
    /**
     *       
     * lodash _.cloneDeep
     */
    var obj1 = {
     name:'wenyuan',
     age: 22,
     social: {
      blog: 'www.wenyuanblog.com'
     },
     skills: ['js', 'html', 'css', 'python']
    }
    var obj2 = _.cloneDeep(obj1);
    console.log(obj1 === obj2) //   false,            
    console.log(obj1.social === obj2.social) //   false,    Object           
    console.log(obj1.skills === obj2.skills) //   false,    Array           
    以上はJavaScriptの中の浅いコピーと深いコピーの知識点で、コードの形式で記録して、回顧に便利です。
    ここでは、Vue親子コンポーネントの送信値に関するいくつかのピットの記事を紹介します。Vue親子コンポーネントに関する詳細な内容は、以前の文章を検索したり、以下の関連記事を見たりしてください。これからもよろしくお願いします。