親がサーバーからデータをロードし、小道具を介して子に渡す親/子コンポーネントのセットアップがあります。子では、親から受信したデータの一部を使用してjQueryカレンダーをインスタンス化します。
カレンダーを設定する前にデータを待つために、子でイベントリスナーを設定している親でイベントをブロードキャストします。
リスナーは子で起動されていますが、I this.$log('theProp')
の場合、未定義です。ただし、VueJs devtoolsでコンポーネントを検査すると、親/子関係が存在し、その間に子が小道具を受け取りました。
小道具は、動的小道具:the-prop="theProp"
として子で定義されます。子供は最終的に小道具を受け取るので、私の設定は正しいと思いますが、何らかの遅延があるようです。親はajax呼び出しのreturn関数で小道具を設定します。また、少し遅れて動作しているようです。
また、子供の小道具にwatch
リスナーを登録して、カレンダーを設定し、小道具がそこにあることを確認しました。ただし、監視リスナーは起動しますが、this.$log('theProp')
は未定義です。
this.$broadcast('dataLoaded', theData)
のように、ブロードキャストコールとともにデータを渡すと、子はそれを正常に受信します。しかし、基本的に独自のプロップハンドラーを構築しているので、そのようにするのは間違っているようです。
コンポーネントがかなり大きく、VueJs devtoolsが親/子の状況が機能していると言っているので、私はコードを投稿していません。
情報が足りませんか?親に値を設定してからそれを受け取る子に値を設定する間にわずかな遅延がありますか?子の親データを待つ適切な方法は何ですか?
通常、データをテンプレートにレンダリングするだけの場合、データはテンプレートにバインドされているため、タイミングはそれほど重要ではありません。しかし、この場合、カレンダーを設定するためにそこにデータが本当に必要です。そうでなければ、データは間違っています。
ありがとう。
編集1:ここにjsfiddleがあります: https://jsfiddle.net/dr3djo0u/1/ データはブロードキャストの直後には利用できません。ただし、ウォッチャーは動作しますが、テストケースをセットアップしたときにthis.$log('someData')
がundefined
を返すことをほぼ誓うことができました。
しかし、私の問題はどこか他の場所にあるのではないかと思います。今夜見てみましょう。今はプロジェクトを持っていません。
編集2:さらにテストを行いました。私の問題は、a)イベントリスナーがデータをすぐに受信しないように見えること、およびb)someData
が既に存在する場合(たとえば、親から来ている場合)、route.data
コールバックでカレンダーを初期化しようとしたことです。そのルートコールバックは、コンポーネントの準備が整う前に呼び出されるため、そこでも機能していませんでした。
私の解決策はこれです:
// works when the child route is loaded directly and parent finishes loading someData
watch: {
someData() {
this.initCalendar();
}
},
// works when navigating from parent (data already loaded)
ready() {
if (this.someData && this.someData.length) {
this.initCalendar()
}
}
私の知る限り、親から子にデータを渡すイベントは必要ありません。
必要なのは、子コンポーネントで:props: ['theProp']
そして、親で子コンポーネントを使用する場合:<child :theProp="someData"></child>
これで、親のどこでsomeData
を変更しても、それに応じて子コンポーネントが反応します。
イベントは必要ありません。「監視」も必要なく、「準備」も必要ありません。
例:AJAX呼び出しの後、親の「準備完了」で、いくつかのデータをロードします。
// at the parent component
data: function () {
return {
someData: {}
}
},
ready: function () {
var vm = this;
$.get(url, function(response) {
vm.someData = response;
});
}
これで、子にデータを渡すために他に何も必要ありません。それはすでにtheProp
として子にあります!
本当に必要なのは、子に、reacts独自のtheProp
プロパティのデータ変更に対して何かを持つことです。
インターフェースのいずれか:
<div v-if="theProp.id > 0">
Loaded!
</div>
またはJavaScriptコードで:
// at the child component
computed: {
// using a computed property based on theProp's value
awesomeDate: function() {
if (!this.theProp || (this.theProp.length === 0)) {
return false;
}
if (!this.initialized) {
this.initCalendar();
}
return this.theProp.someThing;
}
}
アップデート1
親で、子を条件付きでレンダリングすることもできます。
<child v-if="dataLoaded" :theProp="someData"></child>
データが利用可能な場合にのみdataLoaded
をtrueに設定します。
更新2
または、問題が 変更検出の警告 に関連している可能性があります
オブジェクトに新しいプロパティを作成しているかもしれません...
vm.someObject.someProperty = someValue
...いつすべきか...
vm.$set('someObject.someProperty', someValue)
...その他の「警告」の中で。
アップデート3
VueJS 2では、テンプレートに制限されていません。 render function を使用して、必要な最も複雑なレンダリングロジックをコーディングできます。
Update 4(OPについてedit 2)
おそらくready
をドロップしてimmediate
オプションを使用できるため、初期化は1か所で行えます。
watch: {
someData: {
handler: function (someData) {
// check someData and eventually call
this.initCalendar();
},
immediate: true
}
}
props
データのみを使用する子コンポーネントでは、props
の値をdata
に再割り当てする必要はありません。更新バグの原因になります!