2017-09-23 8 views
4

私はオブジェクトpropsを子コンポーネントに渡す必要がある場合があります。Vue2の条件付き小道

最初は、コンポーネント内にフォームとテーブルが含まれていました。このフォームは入力を受け取り、非同期要求が実行され、ユーザーが選択を行うためにテーブルがレンダリングされます。ユーザーはボタンを押してテーブルを隠し、フォームを元に戻してパラメータを再入力することができます。フォームの内容は親の状態に依存していたため、最後の検索パラメータはまだフォームになっていました。

私は、フォームと親のテーブルのサブコンポーネントの両方を作成するためにコンポーネントをリファクタリングするときに問題が発生しました。これでフォームは$emitの親イベントになり、非同期操作が実行され、結果はpropsとしてテーブルに渡されます。これは正常に機能しましたが、ユーザーが「フォームに戻る」ボタンを押すと、フォームが再描画され、状態が初期値にリセットされます。

フォームの内容を親に保存して、propsという形式に戻してみましたが、最初に値を設定するという問題が発生しました。私は直接小道具を変異させたくなかったので、私はこのアプローチを試みた:FormComponent.vue

<template> 
    <!--Some form fields here, bound to data(){}, ommitted for brevity--> 
</template> 
<script> 
    export default{ 
    props:['initialValues'], 
    data(){ 
     return{ 
     //Original structure 
     /*selectedAddress:{ 
      address1: '', 
      address2: '', 
      address3: '', 
      country: '' 
     }*/ 
     selectedAddress: JSON.parse(JSON.stringify(this.initialValues)) //Object.assign({}, this.initialValues) //tried both of these for deep copy 
     } 
    } 
    } 
</script> 

FormContainer.vue

<template> 
    <div v-if="formShown"> 
    <form-component :initialValues="formValues" @formSubmitted="displayResults"></form-component> 
    </div> 
    <div v-if="tableShown"> 
    <table-component :results="fetchedResults" @returnToForm="returnToForm"></table-component> 
    </div> 
</template> 
<script> 
    export default { 
    data(){ 
     return{ 
     formShown: true, 
     tableShown: false, 
     formValues:{ 
      address1: '', 
      address2: '', 
      address3: '', 
      country: '' 
     }, 
     fetchedResults: [] 
     } 
    }, 
    methods:{ 
    async displayResults(){ 
     this.fetchedResults = await someAsynchronousCall(); 
     this.formShown = false; 
     this.tableShown = true; 
    }, 
    returnToForm(){ 
     this.tableShown = false; 
     this.formShown = true; 
    } 
    } 
    } 
</script> 

をこれで問題となったときに、コンポーネントいます最初に作成されたのは、空のオブジェクト(または空のプロパティのみを持つオブジェクト)であり、データプロパティがundefinedとして初期化されていることを意味します。

私は、このように、小道具の値または空の文字列とデータオブジェクトを初期化するために、三元を使用してみました:

data(){ 
    return{ 
    selectedAddress: { 
     address1: this.initialValues.address1 ? this.initialValues.address1 :'', 
     address2: this.initialValues.address2 ? this.initialValues.address2 :'', 
     address3: this.initialValues.address3 ? this.initialValues.address3 :'', 
     country:this.initialValues.country ? this.initialValues.country :'' 
    } 

    } 
}, 

しかし、これはselectedAddressがインスタンスで定義されていないというエラーがスローされますが、レンダリング中に参照されます。私はこれが、三元を使って小道具を初期化するのが間違っていることを推測しています。

mounted(){ 
     if(!this.initialValues || _.isEmpty(this.initialValues)){ 
     Logger.info(`no props passed, no setup needed`); 
     return; 
     } 
     if(this.initalValues.address1){ 
     Logger.info(`setting address 1`); 
     this.selectedAddress.address1 = this.initalValues.address1; 
     } 
     if(this.initialValues.address2){ 
     Logger.info(`setting address 2`); 
     this.selectedAddress.address2 = this.initalValues.address2; 
     } 
     if(this.initialValues.address3){ 
     Logger.info(`setting address 3`); 
     this.selectedAddress.address3 = this.initalValues.address2; 
     } 
     if(this.initialValues.country){ 
     Logger.info(`setting country`); 
     this.selectedAddress.country = this.initalValues.country; 
     } 
    } 

これは、フォームの最初の実行のために動作しますが、this.initialValuesは常にundefinedときです:

私は、このように、mounted(){}ライフサイクルフックに小道具をチェックし、そこにデータプロパティを設定しようとしましたコンポーネントがマウントされます。私はコンポーネントの状態を調べて、initialValuesが存在することを発見しました。ちょうどmountedライフサイクルフックの間ではありません。このアプローチはとにかく「ハッキー」を感じました。

ここからどこに行くのかはわかりません。私はフォームデータをストアにコミットし、フォームが再ロードされた場合に再度取得できますが、親がマウントされている間だけ存在する必要があるものをコミットするような気がしません。

誰でも私にこれを達成するためのより多くの方法を教えてもらえますか?

答えて

0

FormComponentのコードをデータから計算済みにシフトすることで、この問題を解決できるはずです。
計算されたプロパティはリアクティブなので、initialValuesのpropが最終的に何らかのデータを取得したときにフォームに反映されるはずです。
initialValuesが常にaddress1、address2などの構造を持つ場合、Object.assignは機能します(最初はnullであっても)。 (すなわちinitialValues当初= {}でない場合は、プロパティごとのプロパティのチェックを行う必要があります。

<template> 
    <!--Some form fields here, bound to data(){}, ommitted for brevity--> 
    <div>selectedAddress.address1</div> 
    <div>selectedAddress.address2</div> 
</template> 
<script> 
    export default{ 
    props:['initialValues'], 
    data(){ 
    }, 
    computed: { 
     selectedAddress() { 
     return Object.assign({}, this.initialValues) 
     } 
    } 
    } 
</script> 

あなたはEMITを通じてselectedAddressを通過し、それらを適用する必要があり、次のラウンドのためのフォームの値を維持するために、親フォームの値に

私が大好きなのは、フォームがストアからの初期値を取得し、アクションを介してストアにポストバックし、非同期作業を開始し、結果をストアに更新するVuexです。基本的にはdisplayResultsメソッドがアクションになりますが、async..waitは必要ありません。

Vuexはデータを形式化しますあなたはそれをより簡単に推論し、デバッグすることができます。基本的には、データを小道具に渡したり、エミッションから外に出すことを心配する必要はありません。

もう一つは、あなたはV-ショーの代わりに、V-IF FormContainerでを使用してFormComponent値をリセット避けることができると思いました。それはフォームdivを保持するはずですが(それは状態です)、非表示にします。親に対してformValuesを持つ必要はありません。

<template> 
    <div v-show="formShown"> 
    <form-component :initialValues="formValues" @formSubmitted="displayResults"></form-component> 
    </div> 
    <div v-show="tableShown"> 
    <table-component :results="fetchedResults" @returnToForm="returnToForm"></table-component> 
    </div> 
</template> 
+0

私は現在Vuexを使用していますが、私が実装した回避策はVuexを使用しています。私の問題は、ユーザーがフォームをリセットしたときにフォームコンテナの親がDOMから削除されたときなど、適切な時にストアからデータを削除するための正しいアクションをディスパッチすることを忘れないようにする必要があるということですユーザーが親の中からフォームをリセットしたときに、フォーム内からフォームを削除することができます。これは、これがフォームの不正な初期状態を持つ簡単な方法であることがわかります。 – JavaTheNutt

+0

計算されたプロパティを使用すると、フォームがまだ開いている間に、何らかの形で、 'initalValues'の内容が親で変更された場合、フォームフィールドの値自体が変更されますか?私は 'Object.assign()'を使ってフォームの値と親から渡されたデータとの間のリンクを解除しようとしていましたが、これは 'computed(){}'で使われている場合でもそうでしょうか? – JavaTheNutt

+0

私はちょうどフォームを隠すという考え方に似ていますが、複雑さを軽減し、DOMの周りにぶら下がっているのは巨大なコンポーネントではありません。未使用の要素を非表示にするのではなく、削除することは通常受け入れられていますが、この場合は除外を行うことがあります。 – JavaTheNutt

関連する問題