Reaktivität in Vue

Veröffentlicht: 2022-03-10
Kurzzusammenfassung ↬ Reaktivität ist die Fähigkeit einer Variablen (Array, String, Zahl, Objekt usw.), sich zu aktualisieren, wenn ihr Wert oder eine andere Variable, auf die sie verweist, nach der Deklaration geändert wird.

In diesem Artikel werden wir uns mit der Reaktivität in Vue befassen, wie sie funktioniert und wie wir mit neu erstellten Methoden und Funktionen reaktive Variablen erstellen können. Dieser Artikel richtet sich an Entwickler, die die Funktionsweise von Vue 2.x gut verstehen und sich mit dem neuen Vue 3 vertraut machen möchten.

Wir werden eine einfache Anwendung erstellen, um dieses Thema besser zu verstehen. Den Code für diese App finden Sie auf GitHub.

Standardmäßig ist JavaScript nicht reaktiv . Das bedeutet, wenn wir die Variable boy erstellen und in Teil A unserer Anwendung darauf verweisen und dann boy in Teil B ändern, wird Teil A nicht mit dem neuen Wert von boy aktualisiert.

 let framework = 'Vue'; let sentence = `${framework} is awesome`; console.log(sentence) // logs "Vue is awesome" framework = 'React'; console.log(sentence) //should log "React is awesome" if 'sentence' is reactive.

Das obige Snippet ist ein perfektes Beispiel für die nicht reaktive Natur von JavaScript – weshalb sich die Änderung nicht in der sentence widerspiegelt.

In Vue 2.x waren props , computed und data() alle standardmäßig reaktiv, mit Ausnahme von Eigenschaften, die nicht in data vorhanden sind, wenn solche Komponenten erstellt werden. Dies bedeutet, dass, wenn eine Komponente in das DOM eingefügt wird, nur die vorhandenen Eigenschaften im data der Komponente dazu führen würden, dass die Komponente aktualisiert wird, wenn sich solche Eigenschaften ändern.

Intern verwendet Vue 3 das Proxy -Objekt (eine ECMAScript 6-Funktion), um sicherzustellen, dass diese Eigenschaften reaktiv sind, bietet aber weiterhin die Option, Object.defineProperty von Vue 2 für die Internet Explorer-Unterstützung (ECMAScript 5) zu verwenden. Diese Methode definiert eine neue Eigenschaft direkt für ein Objekt oder ändert eine vorhandene Eigenschaft für ein Objekt und gibt das Objekt zurück.

Auf den ersten Blick und da die meisten von uns bereits wissen, dass Reaktivität in Vue nichts Neues ist, mag es unnötig erscheinen, diese Eigenschaften zu nutzen, aber die Options-API hat ihre Grenzen, wenn Sie es mit einer großen Anwendung mit wiederverwendbaren Funktionen in mehreren zu tun haben Teile der Bewerbung. Zu diesem Zweck wurde die neue Kompositions-API eingeführt, um bei der Abstraktion von Logik zu helfen, um eine Codebasis leichter lesbar und wartungsfreundlicher zu machen. Außerdem können wir jetzt ganz einfach jede Variable reaktiv machen, unabhängig von ihrem Datentyp, indem wir eine der neuen Eigenschaften und Methoden verwenden.

Wenn wir die setup -Option verwenden, die als Einstiegspunkt für die Kompositions-API dient, sind das data , computed Eigenschaften und methods nicht zugänglich, da die Komponenteninstanz noch nicht erstellt wurde, wenn das setup ausgeführt wird. Dies macht es unmöglich, die eingebaute Reaktivität in irgendeiner dieser Funktionen in setup zu nutzen. In diesem Tutorial lernen wir alle Möglichkeiten kennen, wie wir dies tun können.

Mehr nach dem Sprung! Lesen Sie unten weiter ↓

Die reaktive Methode

Laut Dokumentation kann die reactive Methode, die das Äquivalent von Vue.observable() in Vue 2.6 ist, nützlich sein, wenn wir versuchen, ein Objekt zu erstellen, dessen Eigenschaften alle reaktiv sind (wie das data in den Options API). Unter der Haube verwendet das data in der Options-API diese Methode, um alle darin enthaltenen Eigenschaften reaktiv zu machen.

Aber wir können unser eigenes reaktives Objekt wie folgt erstellen:

 import { reactive } from 'vue' // reactive state let user = reactive({ "id": 1, "name": "Leanne Graham", "username": "Bret", "email": "[email protected]", "address": { "street": "Kulas Light", "suite": "Apt. 556", "city": "Gwenborough", "zipcode": "92998-3874", "geo": { "lat": "-37.3159", "lng": "81.1496" } }, "phone": "1-770-736-8031 x56442", "website": "hildegard.org", "company": { "name": "Romaguera-Crona", "catchPhrase": "Multi-layered client-server neural-net", "bs": "harness real-time e-markets" }, "cars": { "number": 0 } })

Hier haben wir die reactive Methode aus Vue importiert und dann unsere user deklariert, indem wir ihren Wert als Argument an diese Funktion übergeben haben. Dabei haben wir user reaktiv gemacht, und wenn wir user in unserem Template verwenden und sich entweder das Objekt oder eine Eigenschaft dieses Objekts ändern sollte, dann wird dieser Wert automatisch in diesem Template aktualisiert.

ref

So wie wir eine Methode haben, um Objekte reaktiv zu machen, brauchen wir auch eine, um andere eigenständige primitive Werte (Strings, boolesche Werte, undefinierte Werte, Zahlen usw.) und Arrays reaktiv zu machen. Während der Entwicklung arbeiteten wir mit diesen anderen Datentypen, mussten aber auch reaktiv sein. Der erste Ansatz, den wir uns vorstellen könnten, wäre, reactive zu verwenden und den Wert der Variablen zu übergeben, die wir reaktiv machen möchten.

 import { reactive } from 'vue' const state = reactive({ users: [], });

Da reactive eine tiefe reaktive Konvertierung hat, wäre der user als Eigenschaft ebenfalls reaktiv, wodurch unser Ziel erreicht würde; Daher würde der user immer überall dort aktualisieren, wo es in der Vorlage einer solchen App verwendet wird. Aber mit der Eigenschaft ref können wir jede Variable mit jedem Datentyp reaktiv machen, indem wir den Wert dieser Variablen an ref übergeben. Diese Methode funktioniert auch für Objekte, verschachtelt das Objekt jedoch eine Ebene tiefer als bei Verwendung der reactive Methode.

 let property = { rooms: '4 rooms', garage: true, swimmingPool: false } let reactiveProperty = ref(property) console.log(reactiveProperty) // prints { // value: {rooms: "4 rooms", garage: true, swimmingPool: false} // }

Unter der Haube nimmt ref dieses übergebene Argument und konvertiert es in ein Objekt mit einem Schlüssel von value . Das heißt, wir können auf unsere Variable zugreifen, indem wir variable.value aufrufen, und wir können auch ihren Wert ändern, indem wir sie auf die gleiche Weise aufrufen.

 import {ref} from 'vue' let age = ref(1) console.log(age.value) //prints 1 age.value++ console.log(age.value) //prints 2

Damit können wir ref in unsere Komponente importieren und eine reaktive Variable erstellen:

 <template> <div class="home"> <form @click.prevent=""> <table> <tr> <th>Name</th> <th>Username</th> <th>email</th> <th>Edit Cars</th> <th>Cars</th> </tr> <tr v-for="user in users" :key="user.id"> <td>{{ user.name }}</td> <td>{{ user.username }}</td> <td>{{ user.email }}</td> <td> <input type="number" name="cars" v-model.number="user.cars.number" /> </td> <td> <cars-number :cars="user.cars" /> </td> </tr> </table> <p>Total number of cars: {{ getTotalCars }}</p> </form> </div> </template> <script> // @ is an alias to /src import carsNumber from "@/components/cars-number.vue"; import axios from "axios"; import { ref } from "vue"; export default { name: "Home", data() { return {}; }, setup() { let users = ref([]); const getUsers = async () => { let { data } = await axios({ url: "data.json", }); users.value = data; }; return { users, getUsers, }; }, components: { carsNumber, }, created() { this.getUsers(); }, computed: { getTotalCars() { let users = this.users; let totalCars = users.reduce(function(sum, elem) { return sum + elem.cars.number; }, 0); return totalCars; }, }; </script>

Hier haben wir ref importiert, um eine reaktive users in unserer Komponente zu erstellen. Wir haben dann axios importiert, um Daten aus einer JSON-Datei im public Ordner abzurufen, und wir haben unsere carsNumber Komponente importiert, die wir später erstellen werden. Als nächstes haben wir eine reaktive users mit der ref -Methode erstellt, damit users aktualisieren können, wann immer sich die Antwort aus unserer JSON-Datei ändert.

Wir haben auch eine getUser Funktion erstellt, die das users aus unserer JSON-Datei mit Axios abruft, und wir haben den Wert aus dieser Anfrage der users zugewiesen. Schließlich haben wir eine berechnete Eigenschaft erstellt, die die Gesamtzahl der Autos berechnet, die unsere Benutzer haben, da wir sie im Vorlagenabschnitt geändert haben.

Es ist wichtig zu beachten, dass beim Zugriff auf ref Eigenschaften, die im Vorlagenabschnitt oder außerhalb von setup() zurückgegeben werden, diese automatisch flach ausgepackt werden. Das bedeutet, dass refs , die ein Objekt sind, immer noch einen .value benötigen, um darauf zugreifen zu können. Da es sich bei users um ein Array handelt, könnten wir einfach users und nicht users.value in getTotalCars .

Im Vorlagenabschnitt haben wir eine Tabelle angezeigt, die die Informationen jedes Benutzers zusammen mit einer <cars-number /> Komponente anzeigt. Diese Komponente akzeptiert eine cars -Requisite, die in der Zeile jedes Benutzers als Anzahl der Autos angezeigt wird, die er hat. Dieser Wert wird immer dann aktualisiert, wenn sich der Wert von cars im Benutzerobjekt ändert. Genau so würde das data oder computed Eigenschaft funktionieren, wenn wir mit der Options-API arbeiten würden.

toRefs

Wenn wir die Composition API verwenden, akzeptiert die setup Funktion zwei Argumente: props und context . Diese props werden von der Komponente an setup() übergeben und ermöglichen den Zugriff auf die Requisiten, die die Komponente innerhalb dieser neuen API hat. Diese Methode ist besonders nützlich, da sie die Destrukturierung von Objekten ermöglicht, ohne ihre Reaktivität zu verlieren.

 <template> <p>{{ cars.number }}</p> </template> <script> export default { props: { cars: { type: Object, required: true, }, gender: { type: String, required: true, }, }, setup(props) { console.log(props); // prints {gender: "female", cars: Proxy} }, }; </script> <style></style>

Um einen Wert zu verwenden, der ein Objekt von props in der Kompositions-API ist, und gleichzeitig sicherzustellen, dass er seine Reaktivität beibehält, verwenden wir toRefs . Diese Methode nimmt ein reaktives Objekt und wandelt es in ein einfaches Objekt um, in dem jede Eigenschaft des ursprünglichen reaktiven Objekts zu einer ref wird. Das bedeutet, dass die cars stützen…

 cars: { number: 0 }

… würde jetzt das werden:

 { value: cars: { number: 0 }

Damit können wir cars in jedem Teil der Setup-API verwenden und gleichzeitig ihre Reaktivität beibehalten.

 setup(props) { let { cars } = toRefs(props); console.log(cars.value); // prints {number: 0} },

Wir können diese neue Variable mit der Überwachung der Kompositions-API watch und auf diese Änderung reagieren, wie wir möchten.

 setup(props) { let { cars } = toRefs(props); watch( () => cars, (cars, prevCars) => { console.log("deep ", cars.value, prevCars.value); }, { deep: true } ); }

toRef

Ein weiterer häufiger Anwendungsfall, mit dem wir konfrontiert werden könnten, ist die Übergabe eines Werts , der nicht unbedingt ein Objekt ist, sondern einer der Datentypen, die mit ref arbeiten (Array, Zahl, String, Boolean usw.). Mit toRef können wir eine reaktive Eigenschaft (dh ref ) aus einem reaktiven Quellobjekt erstellen. Dadurch würde sichergestellt, dass die Eigenschaft reaktiv bleibt und aktualisiert wird, wenn sich die übergeordnete Quelle ändert.

 const cars = reactive({ Toyota: 1, Honda: 0 }) const NumberOfHondas = toRef(state, 'Honda') NumberOfHondas.value++ console.log(state.Honda) // 1 state.Honda++ console.log(NumberOfHondas.value) // 2

Hier haben wir mit der reactive Methode ein reaktives Objekt mit den Eigenschaften Toyota und Honda erstellt. Wir haben auch toRef verwendet, um eine reaktive Variable aus Honda zu erstellen. Aus dem obigen Beispiel können wir sehen, dass der Wert in beiden Fällen aktualisiert wird, wenn wir Honda entweder mit dem reaktiven cars -Objekt oder NumberOfHondas aktualisieren.

Diese Methode ist ähnlich und doch so verschieden von der toRefs Methode, die wir oben behandelt haben, in dem Sinne, dass sie ihre Verbindung zu ihrer Quelle beibehält und für Strings, Arrays und Zahlen verwendet werden kann. Anders als bei toRefs müssen wir uns zum Zeitpunkt der Erstellung keine Gedanken über die Existenz der Eigenschaft in ihrer Quelle machen, denn wenn diese Eigenschaft zum Zeitpunkt der Erstellung dieser ref nicht vorhanden ist und stattdessen null zurückgibt, würde sie dennoch gespeichert werden als gültige Eigenschaft, mit einer Form von watcher , so dass, wenn sich dieser Wert ändert, diese mit ref erstellte toRef ebenfalls aktualisiert wird.

Wir können diese Methode auch verwenden, um eine reaktive Eigenschaft aus props zu erstellen. Das würde so aussehen:

 <template> <p>{{ cars.number }}</p> </template> <script> import { watch, toRefs, toRef } from "vue"; export default { props: { cars: { type: Object, required: true, }, gender: { type: String, required: true, }, }, setup(props) { let { cars } = toRefs(props); let gender = toRef(props, "gender"); console.log(gender.value); watch( () => cars, (cars, prevCars) => { console.log("deep ", cars.value, prevCars.value); }, { deep: true } ); }, }; </script>

Hier haben wir eine ref erstellt, die auf der von props erhaltenen gender basiert. Dies ist praktisch, wenn wir zusätzliche Operationen an der Requisite einer bestimmten Komponente durchführen möchten.

Fazit

In diesem Artikel haben wir uns angesehen, wie Reaktivität in Vue funktioniert, indem wir einige der neu eingeführten Methoden und Funktionen von Vue 3 verwendet haben. Wir haben uns zunächst angesehen, was Reaktivität ist und wie Vue das Proxy Objekt hinter den Kulissen verwendet, um dies zu erreichen. Wir haben uns auch angesehen, wie wir mit reactive Objekten reaktive Objekte und mit ref reaktive Eigenschaften erstellen können.

Schließlich haben wir uns angesehen, wie man reaktive Objekte in einfache Objekte umwandelt, deren Eigenschaften jeweils eine ref sind, die auf die entsprechende Eigenschaft des ursprünglichen Objekts verweist, und wir haben gesehen, wie man eine ref für eine Eigenschaft auf einem reaktiven Quellobjekt erstellt.

Weitere Ressourcen

  • „Proxy“ (Objekt), MDN Web Docs
  • „Grundlagen der Reaktivität“, Vue.js
  • „Referenzen“, Vue.js
  • „Lifecycle-Hook-Registrierung im setup “, Vue.js