2016-09-26 15 views
7

Mam ustawienie komponentu nadrzędnego/podrzędnego, w którym rodzic ładuje dane z serwera i przekazuje je dzieciom za pośrednictwem rekwizytów. W dziecku chciałbym utworzyć instancję kalendarza jQuery z niektórymi danymi, które otrzymuje od rodzica.Komponenty komponentów potomnych VueJs nie aktualizują się natychmiast

Aby czekać na dane przed skonfigurowaniem kalendarza, rozgłaszam zdarzenie w obiekcie nadrzędnym, w którym mam ustawienie detektora zdarzeń dla dziecka.

Słuchacz jest wywoływany u dziecka, ale jeśli I this.$log('theProp'), jest niezdefiniowany. Jednakże, jeśli sprawdzę komponenty za pomocą devtools VueJs, związek rodzic/dziecko jest tam i dziecko otrzymało rekwizyt w międzyczasie.

Prop jest zdefiniowany na dziecku jako dynamiczny prop :the-prop="theProp". Ponieważ dziecko w końcu otrzymuje rekwizyt, zakładam, że moje ustawienie jest poprawne, ale wydaje się, że istnieje pewne opóźnienie. Rodzic ustawia rekwizyty w funkcji powrotu wywołania ajax i znowu: działa, z niewielkim opóźnieniem.

Próbowałem także zarejestrować słuchacza watch na rekwizycie, aby móc ustawić kalendarz i upewnić się, że rekwizyt jest dostępny. Jednak detektor zegarka zostaje uruchomiony, ale this.$log('theProp') jest nadal niezdefiniowany.

Jeśli przekazuję dane wraz z połączeniem broadcast, np. this.$broadcast('dataLoaded', theData), dziecko otrzymuje je w porządku. Ale wydaje mi się, że nie robię tego w ten sposób, ponieważ w zasadzie buduję swojego własnego pomocnika.

Nie publikuję żadnego kodu, ponieważ komponenty są dość duże, a devtools VueJs mówią mi, że sytuacja rodzica/dziecka działa.

Czy brakuje mi niektórych informacji? Czy istnieje niewielkie opóźnienie między ustawieniem wartości w rodzicu a dzieckiem, które je otrzymuje? Jaki byłby właściwy sposób oczekiwania na dane macierzyste dziecka?

Zwykle podczas renderowania danych do szablonu, czas nie ma tak dużego znaczenia, ponieważ dane są powiązane z szablonem. Ale w tym przypadku naprawdę potrzebuję danych, aby ustawić kalendarz, bo inaczej będzie źle.

Dzięki.

edit 1: oto jsfiddle: https://jsfiddle.net/dr3djo0u/1/ To zdaje się potwierdzać, że dane nie są dostępne natychmiast po zakończeniu transmisji. Obserwator działa, chociaż mógłbym prawie przysiąc, że czasami this.$log('someData') zwrócił undefined, kiedy ustawiłem tę walizkę.

Ale myślę, że mój problem może być gdzieś indziej, dziś będę wyglądał, nie mam teraz projektu ze mną.

edytuj 2: zrobił kilka dodatkowych testów. Mój problem polegał na tym, że a) detektory zdarzeń nie wydają się natychmiast odbierać danych i b) Próbowałem również zainicjować kalendarz w wywołaniu zwrotnym route.data, jeśli już byłam w pobliżu (np. Gdy pochodzi z nadrzędnego), ale to wywołanie zwrotne trasy nazywa się zanim komponent będzie gotowy, więc też nie działał.

Moje rozwiązanie jest teraz to:

// 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() 
    } 
} 
+1

Hi można dostarczyć prosty przykład kodu do odtworzenia problemu? – Nora

+2

Jeśli "obserwujesz" zmienną, a jej wartość wewnątrz 'watch' jest niezdefiniowana, to znaczy, że coś jest ustawione na niezdefiniowane. –

+0

Dzięki za komentarze. Zaktualizowałem moje pytania z tym, co odkryłem. – Chris

Odpowiedz

3

O ile mi wiadomo, nie ma potrzeby zdarzenia do przekazywania danych z rodzica na dziecko.

Wszystko czego potrzebujesz jest w składniku dziecko: props: ['theProp']

I przy użyciu komponentu dzieci w dominującej: <child :theProp="someData"></child>

Teraz, gdziekolwiek w dominującej Państwo zmienić someData składnik dziecko będzie odpowiednio reagować .

Nie potrzebujesz wydarzeń, nie potrzebujesz "oglądania", nie potrzebujesz "gotowości".


Na przykład: po wywołaniu AJAX, w rodziców „gotowy”, załadować jakieś dane:

// at the parent component 

data: function() { 
    return { 
    someData: {} 
    } 
}, 

ready: function() { 
    var vm = this; 
    $.get(url, function(response) { 
    vm.someData = response; 
    }); 
} 

Teraz nie trzeba nic więcej do przekazania danych do dziecka. Jest już w dziecku jako theProp!

To, co naprawdę trzeba zrobić, to mieć coś, co w przypadku dziecka reaguje na zmiany danych we własnej własności .

Albo w interfejsie:

<div v-if="theProp.id > 0"> 
    Loaded! 
</div> 

Lub w kodzie 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; 
    } 
} 

Update 1

Można również, w dominującej, czyni dziecko warunkowo:

<child v-if="dataLoaded" :theProp="someData"></child> 

Ustaw tylko dataLoaded na true, gdy dane są dostępne.

Aktualizacja 2

A może Twój problem jest związany z change detection caveat

Może jesteś tworząc nową właściwość w obiekcie ...

vm.someObject.someProperty = someValue 

... kiedy powinieneś zrobić ...

vm.$set('someObject.someProperty', someValue) 

... między innymi "zastrzeżeniami".

Update 3

W VueJS 2 nie są ograniczone do szablonów. Można użyć kodu render function i kodować najbardziej złożoną logikę renderowania.

Update 4 (dotyczy OP edit 2)

Może spaść ready i używać immediate opcji, więc inicjalizacji jest w jednym miejscu:

watch: { 
    someData: { 
    handler: function (someData) { 
     // check someData and eventually call 
     this.initCalendar(); 
    }, 
    immediate: true 
    } 
} 
+0

Przekazuję dane za pośrednictwem rekwizytów, moje pytanie dotyczy reagowania na otrzymywanie zmian danych, ponieważ muszę inicjować różne rzeczy w zależności od tego. Obliczone właściwości nie są drogą do tego typu rzeczy. – Chris

+0

Zaktualizowałem moją odpowiedź, w tym inne sugestie. Jednak imho, obliczone właściwości są miłe dla tego przypadku. Możesz stworzyć właściwość 'isReady' lub' isLoaded', opartą na 'someData'. W rzeczywistości, jeśli chcesz zareagować na zmiany danych, obliczona właściwość ** jest ** drogą do zrobienia. –

+0

podczas korzystania z szablonów, tak. W metodzie, jeśli sprawdzam 'if (this.isLoaded)' i nie jest ono załadowane w tym czasie, tracę moją szansę na utworzenie instancji kalendarza. Tak więc, muszę oglądać dane do zmian, jak opisano w mojej drugiej aktualizacji. Działa dobrze. – Chris

Powiązane problemy