Zacząłem https://laracasts.com/series/learning-vue-step-by-step series. Zatrzymałem się na lekcji Vue, Laravel i AJAX z tym błędem:
vue.js: 2574 [Vue warn]: Unikaj bezpośredniego modyfikowania właściwości, ponieważ wartość zostanie nadpisana przy każdym ponownym renderowaniu komponentu nadrzędnego. Zamiast tego użyj danych lub obliczonej właściwości opartej na wartości właściwości. Mutacja rekwizytu: „lista” (znaleziona w komponencie)
Mam ten kod w main.js.
Vue.component('task', {
template: '#task-template',
props: ['list'],
created() {
this.list = JSON.parse(this.list);
}
});
new Vue({
el: '.container'
})
Wiem, że problem pojawia się w created (), kiedy nadpisuję właściwość listy, ale jestem nowicjuszem w Vue, więc kompletnie nie wiem, jak to naprawić. Czy ktoś ma pomysł, jak (i proszę wyjaśnić, dlaczego) to naprawić?
javascript
vue.js
vuejs2
Dariusz Chowański
źródło
źródło
Odpowiedzi:
Ma to związek z faktem, że lokalna mutacja rekwizytu jest uważana za anty-wzorzec w Vue 2
To, co powinieneś teraz zrobić, jeśli chcesz lokalnie zmutować właściwość , to zadeklarować w swoim polu,
data
które używaprops
wartości jako wartości początkowej, a następnie zmutować kopię:Możesz przeczytać więcej na ten temat w oficjalnym przewodniku Vue.js.
Uwaga 1: Należy pamiętać, że należy nie używać tego samego nazwę dla
prop
adata
, czyli:Uwaga 2: Ponieważ czuję, że istnieje pewne zamieszanie dotyczące
props
i reaktywności , proponuję rzucić okiem na ten wątekźródło
Wzór Vue jest w
props
dół i wevents
górę. Brzmi prosto, ale łatwo o tym zapomnieć, pisząc komponent niestandardowy.Od wersji Vue 2.2.0 możesz używać modelu v (z obliczonymi właściwościami ). Odkryłem, że ta kombinacja tworzy prosty, czysty i spójny interfejs między komponentami:
props
przekazany do twojego komponentu pozostaje reaktywny (tj. Nie jest sklonowany ani nie wymagawatch
funkcji aktualizowania kopii lokalnej po wykryciu zmian).Obliczona właściwość umożliwia oddzielne definiowanie metody ustawiającej i pobierającej. Pozwala to
Task
na przepisanie komponentu w następujący sposób:Właściwość modelu określa, z którym elementem
prop
jest skojarzonyv-model
i które zdarzenie będzie emitowane przy zmianie. Następnie możesz wywołać ten komponent od rodzica w następujący sposób:Właściwość
listLocal
computed zapewnia prosty interfejs pobierający i ustawiający w komponencie (myśl o tym jak o zmiennej prywatnej). Wewnątrz#task-template
możesz renderowaćlistLocal
i pozostanie reaktywny (tj. JeśliparentList
zmieni się, zaktualizujeTask
komponent). Możesz także dokonać mutacjilistLocal
, wywołując ustawiającego (np.this.listLocal = newList
), A wyśle on zmianę do rodzica.Wspaniałe w tym wzorcu jest to, że możesz przekazać
listLocal
do komponentu potomnegoTask
(używającv-model
), a zmiany z komponentu potomnego będą propagowane do komponentu najwyższego poziomu.Załóżmy na przykład, że mamy oddzielny
EditTask
komponent do wykonywania pewnych modyfikacji danych zadania. Korzystając z tego samegov-model
i obliczonego wzorca właściwości możemy przekazaćlistLocal
komponentowi (używającv-model
):Jeśli
EditTask
emituje zmiana będzie to odpowiednio zadzwonićset()
nalistLocal
iw ten sposób propagować wydarzenie na najwyższym poziomie. PodobnieEditTask
komponent może również wywoływać inne komponenty podrzędne (takie jak elementy formularzy) za pomocąv-model
.źródło
Vue tylko ostrzega: zmieniasz właściwość w komponencie, ale kiedy komponent nadrzędny ponownie się wyrenderuje, „lista” zostanie nadpisana i stracisz wszystkie zmiany. Jest to więc niebezpieczne.
Zamiast tego użyj właściwości obliczonej w ten sposób:
źródło
Jeśli używasz Lodash, możesz sklonować rekwizyt przed zwróceniem go. Ten wzorzec jest przydatny, jeśli zmodyfikujesz ten element zarówno dla rodzica, jak i dziecka.
Powiedzmy, że mamy listę właściwości na siatce komponentów .
W komponencie nadrzędnym
W komponencie podrzędnym
źródło
Rekwizyty w dół, wydarzenia w górę. To wzór Vue. Chodzi o to, że jeśli spróbujesz zmutować rekwizyty przechodzące od rodzica. To nie zadziała i po prostu zostanie wielokrotnie nadpisane przez komponent nadrzędny. Składnik podrzędny może emitować tylko zdarzenie, aby powiadomić składnik nadrzędny o wykonaniu czegoś. Jeśli nie podoba ci się te ograniczenie, możesz użyć VUEX (w rzeczywistości ten wzór będzie wessał złożoną strukturę komponentów, powinieneś użyć VUEX!)
źródło
Nie powinieneś zmieniać wartości właściwości w komponencie potomnym. Jeśli naprawdę potrzebujesz go zmienić, możesz użyć
.sync
. Takie jak to<your-component :list.sync="list"></your-component>
źródło
Zgodnie z VueJs 2.0 nie powinieneś modyfikować właściwości wewnątrz komponentu. Mutują je tylko rodzice. Dlatego powinieneś zdefiniować zmienne w danych o różnych nazwach i aktualizować je, obserwując rzeczywiste rekwizyty. W przypadku zmiany właściwości listy przez rodzica, możesz ją przeanalizować i przypisać do mutableList. Oto kompletne rozwiązanie.
Używa mutableList do renderowania twojego szablonu, więc zachowujesz bezpieczną propozycję listy w komponencie.
źródło
nie zmieniaj właściwości bezpośrednio w komponentach. jeśli chcesz to zmienić, ustaw nową właściwość w następujący sposób:
I zmień wartość listClone.
źródło
Odpowiedź jest prosta, należy przerwać bezpośrednią mutację prop, przypisując wartość do niektórych lokalnych zmiennych składowych (może to być właściwość data, obliczana za pomocą metod pobierających, ustawiających lub obserwatorów).
Oto proste rozwiązanie przy użyciu obserwatora.
To jest to, czego używam do tworzenia dowolnych komponentów do wprowadzania danych i działa dobrze. Wszelkie nowe dane wysłane (v-model (ed)) od rodzica będą obserwowane przez obserwatora wartości i są przypisywane do zmiennej wejściowej, a po otrzymaniu danych wejściowych możemy złapać tę akcję i wysłać dane wejściowe do rodzica, sugerując, że dane są wprowadzane z elementu formularza.
źródło
Miałem też do czynienia z tym problemem. Ostrzeżenie zniknęło po użyciu
$on
i$emit
. Jest to coś w rodzaju użycia$on
i$emit
zalecanego przesyłania danych z komponentu podrzędnego do komponentu nadrzędnego.źródło
Jeśli chcesz zmienić właściwości - użyj obiektu.
składnik:
źródło
Musisz dodać taką metodę obliczeniową
component.vue
źródło
jednokierunkowy przepływ danych, zgodnie z https://vuejs.org/v2/guide/components.html , komponent podąża za jednokierunkowym przepływem danych, wszystkie rekwizyty tworzą jednokierunkowe powiązanie między własnością podrzędną a rodzicem po pierwsze, kiedy właściwość nadrzędna zostanie zaktualizowana, będzie spływać do dziecka, ale nie na odwrót. Zapobiega to przypadkowej mutacji składników podrzędnych, co może utrudnić zrozumienie przepływu danych w aplikacji.
Ponadto za każdym razem, gdy komponent nadrzędny jest aktualizowany, wszystkie właściwości w komponentach potomnych zostaną odświeżone o najnowszą wartość. Oznacza to, że nie powinieneś próbować modyfikować właściwości wewnątrz komponentu potomnego. Jeśli to zrobisz .vue wyświetli ostrzeżenie w konsoli.
Istnieją zazwyczaj dwa przypadki, w których kuszące jest modyfikowanie właściwości: Właściwość służy do przekazywania wartości początkowej; komponent potomny chce go później użyć jako lokalnej właściwości danych. Rekwizyt jest przekazywany jako wartość surowa, którą należy przekształcić. Prawidłową odpowiedzią na te przypadki użycia są: Zdefiniuj lokalną właściwość danych, która używa wartości początkowej właściwości jako wartości początkowej:
Zdefiniuj obliczoną właściwość, która jest obliczana na podstawie wartości właściwości:
źródło
Rekwizyty Vue.js nie powinny być modyfikowane, ponieważ w Vue jest to uważane za Anty-Pattern.
Podejście trzeba będzie podjąć jest tworzenie własności danych na składniku że odniesienia oryginalny prop własnością listy
Teraz twoja struktura listy, która jest przekazywana do komponentu, jest przywoływana i mutowana przez
data
właściwość twojego komponentu :-)Jeśli chcesz zrobić coś więcej niż tylko przeanalizować właściwość listy, użyj właściwości komponentu Vue
computed
. To pozwoli ci na głębsze mutacje twoich rekwizytów.Powyższy przykład analizuje twoją właściwość listy i filtruje ją tylko do aktywnych list- temów, wylogowuje ją w poszukiwaniu schnittów i chichotów i zwraca.
Uwaga : w szablonie znajdują się odwołania do obu
data
&computed
właściwości, npŁatwo jest pomyśleć, że
computed
właściwość (będąca metodą) musi zostać nazwana ... tak nie jestźródło
Może to zaspokoi Twoje potrzeby.
źródło
Dodając do najlepszej odpowiedzi,
Ustawienie właściwości przez tablicę jest przeznaczone do tworzenia / tworzenia prototypów, w produkcji upewnij się, że ustawiłeś typy właściwości ( https://vuejs.org/v2/guide/components-props.html ) i ustaw domyślną wartość na wypadek, gdyby prop nie zostały wypełnione przez rodzica, jako takie.
W ten sposób otrzymasz przynajmniej pusty obiekt
mutableList
zamiast błędu JSON.parse, jeśli jest on niezdefiniowany.źródło
Vue.js uważa to za anty-wzór. Na przykład deklarowanie i ustawianie niektórych rekwizytów, takich jak
Aby rozwiązać ten problem, musisz wziąć wartość z właściwości do danych lub obliczonej właściwości instancji Vue, na przykład:
To na pewno zadziała.
źródło
Oprócz powyższego, dla innych osób mających następujący problem:
„Jeśli wartość właściwości nie jest wymagana i nie zawsze jest zwracana, przekazane dane zwróciłyby
undefined
(zamiast byłyby puste)”. Co może zepsuć<select>
wartość domyślną, rozwiązałem to, sprawdzając, czy wartość jest ustawiona wbeforeMount()
(i ustaw ją, jeśli nie) w następujący sposób:JS:
HTML:
źródło
Chcę udzielić odpowiedzi, która pomoże uniknąć używania dużej ilości kodu, obserwatorów i obliczonych właściwości. W niektórych przypadkach może to być dobre rozwiązanie:
Rekwizyty mają na celu zapewnienie jednostronnej komunikacji.
Kiedy masz
show/hide
przycisk modalny z rekwizytem, najlepszym rozwiązaniem dla mnie jest emitowanie zdarzenia:Następnie dodaj detektor do elementu modalnego:
(W tym przypadku rekwizyt
show
prawdopodobnie nie jest potrzebny, ponieważ można użyć łatwegov-if="show"
bezpośrednio na bazie modalnej)źródło
Osobiście zawsze sugeruję, że jeśli musisz zmutować rekwizyty, najpierw przekaż je do obliczonej własności i wróć stamtąd, potem można łatwo mutować rekwizyty, nawet wtedy, gdy możesz śledzić mutację rekwizytów, jeśli te są mutowane z innego komponent też lub możemy obejrzeć również.
źródło
Ponieważ właściwości Vue to jednokierunkowy przepływ danych, zapobiega to przypadkowej zmianie stanu rodzica przez komponenty potomne.
Z oficjalnego dokumentu Vue znajdziemy 2 sposoby rozwiązania tego problemu
jeśli komponent potomny chce używać właściwości jako danych lokalnych, najlepiej jest zdefiniować lokalną właściwość danych.
Rekwizyt jest przekazywany jako wartość surowa, którą należy przekształcić. W tym przypadku najlepiej jest zdefiniować obliczoną właściwość za pomocą wartości właściwości:
źródło
TAK !, mutowanie atrybutów w vue2 jest anty-wzorcem. ALE ... Po prostu złam zasady, stosując inne zasady i idź naprzód! To, czego potrzebujesz, to dodanie modyfikatora .sync do atrybutu komponentu w zakresie paret.
<your-awesome-components :custom-attribute-as-prob.sync="value" />
🤡 To proste, że zabijemy batmana 😁
źródło
Kiedy TypeScript jest preferowanym językiem. rozwoju
i nie
źródło
Poniżej znajduje się składnik batonika, kiedy podaję batonik zmienną bezpośrednio do modelu v w ten sposób, jeśli zadziała, ale w konsoli da błąd jako
Unikaj bezpośredniego modyfikowania właściwości, ponieważ wartość zostanie nadpisana przy każdym ponownym renderowaniu komponentu nadrzędnego. Zamiast tego użyj danych lub obliczonej właściwości opartej na wartości właściwości.
Poprawnym sposobem na pozbycie się tego błędu mutacji jest użycie obserwatora
Więc w głównym komponencie, w którym załadujesz ten batonik, możesz po prostu zrobić ten kod
To zadziałało dla mnie
źródło