Während ich diesen Artikel schreibe, nähern wir uns der Veröffentlichung von Vue 3. Meiner Meinung nach ist es am interessantesten zu beobachten, wie andere Entwickler ihn wahrnehmen und verwenden. Ich hatte in den letzten Monaten die Gelegenheit, mit Vue 3 herumzuspielen, aber ich weiß, dass es diejenigen gibt, die dies nicht getan haben.
Die wichtigste Neuerung in der neuen Version ist die Composition API. Es bietet einen alternativen Ansatz zum Erstellen von Komponenten und unterscheidet sich stark von der vorhandenen Options-API. Es fällt mir nicht schwer zuzugeben, dass ich ihn nicht verstanden habe, als ich ihn zum ersten Mal sah. Als es jedoch angewendet wurde, begann sich eine Bedeutung zu entwickeln. Möglicherweise schreiben Sie nicht Ihre gesamte Anwendung mithilfe der Kompositions-API neu. In diesem Artikel können Sie jedoch darüber nachdenken, wie die Erstellung und Komposition von Komponenten funktioniert.
Ich habe kürzlich einige Präsentationen durchgeführt, und eine häufig gestellte Frage war, wann ich Ref und wann Reactive verwende, um eine reaktive Eigenschaft zu deklarieren. Ich hatte keine gute Antwort und brauchte ein paar Wochen, um die Antwort zu finden. Dieser Artikel ist das Ergebnis meiner Forschung.
Ich möchte auch darauf hinweisen, dass das oben Gesagte meine Meinung ist, und bitte denken Sie nicht, dass es notwendig ist, "nur so und nicht anders" zu tun. Ich habe vor, Ref und Reactive auf diese Weise zu verwenden, bis jemand etwas anderes empfiehlt oder bis ich selbst einen besseren Ansatz gefunden habe. Ich denke, es dauert einige Zeit, um neue Technologien zu verstehen, und dann können bewährte Techniken auftauchen.
Bevor Sie fortfahren, gehe ich davon aus, dass Sie sich zumindest kurz mit der Kompositions-API vertraut machen und verstehen, woraus sie besteht. Dieser Artikel konzentriert sich eher auf die Unterschiede zwischen ref und reaktiv als auf den API-Zusammensetzungsmechanismus.
Vue 2 Reaktivität
Um Sie auf den neuesten Stand zu bringen, werde ich einen kurzen Blick darauf werfen, wie reaktive Eigenschaften in einer Vue 2-Anwendung erstellt werden. Wenn Sie möchten, dass Vue 2 Änderungen an Eigenschaften verfolgt, müssen Sie diese in dem von der Datenfunktion zurückgegebenen Objekt deklarieren.
<template>
<h1>{{ title }}</h1>
</template>
<script>
export default {
data() {
return {
title: "Hello, Vue!"
};
}
};
</script>
Unter der Haube von Vue 2 wird Object.defineProperty () für jede Eigenschaft aufgerufen, um einen Getter und Setter zum Verfolgen von Änderungen zu erstellen. Dies ist die einfachste Erklärung des Prozesses und ich möchte die Idee vermitteln: Es ist keine Magie darin. Sie können nirgendwo reaktive Eigenschaften erstellen und erwarten, dass Vue Änderungen daran verfolgt. Sie müssen reaktive Eigenschaften in der Datenfunktion festlegen.
REF und REAKTIV
Bei der Arbeit mit der Options-API müssen beim Deklarieren reaktiver Eigenschaften einige Regeln beachtet werden, genau wie bei der Composition-API. Sie können nicht einfach eine Eigenschaft erstellen und Reaktivität erwarten. Im folgenden Beispiel habe ich die title-Eigenschaft deklariert und die Funktion setup () gibt sie zurück, wodurch sie der Vorlage zur Verfügung gestellt wird.
<template>
<h1>{{ title }}</h1>
</template>
<script>
export default {
setup() {
let title = "Hello, Vue 3!";
return { title };
}
};
</script>
Dies funktioniert, aber die title-Eigenschaft ist nicht reaktiv. Jene. Wenn jemand den Titel ändert, werden diese Änderungen NICHT im Haus wiedergegeben. Wenn Sie beispielsweise den Titel nach 5 Sekunden ändern, ändert der folgende Code NICHT die Startseite.
<template>
<h1>{{ title }}</h1>
</template>
<script>
export default {
setup() {
let title = "Hello, Vue 3!";
setTimeout(() => {
title = "THIS IS A NEW TITLE";
}, 5000);
return { title };
}
};
</script>
Wir können ref importieren und verwenden, um die Eigenschaft reaktiv zu machen. Unter der Haube erstellt Vue 3 einen Proxy .
<template>
<h1>{{ title }}</h1>
</template>
<script>
import { ref } from "vue";
export default {
setup() {
const title = ref("Hello, Vue 3!");
setTimeout(() => {
// , .value ...
//
title.value = "New Title";
}, 5000);
return { title };
}
};
</script>
Ich möchte klarstellen, dass es in Bezug auf Ref und Reactive zwei verschiedene Fälle gibt. Die erste besteht darin, eine Komponente wie im obigen Beispiel zu erstellen, und Sie benötigen reaktive Eigenschaften. Die zweite Möglichkeit besteht darin, Funktionen zu erstellen, mit denen die Komposition in Komponenten und Funktionen verwendet werden kann. Wir werden beide Szenarien in diesem Artikel diskutieren.
REF
Wenn Sie Eigenschaften einfacher Typen erstellen, ist ref () Ihre erste Wahl. Es ist keine Silberkugel, aber es lohnt sich, damit zu beginnen. Ich möchte Sie an sieben primitive Typen in JavaScript erinnern:
- String
- Nummer
- BigInt
- Boolescher Wert
- Symbol
- Null
- Nicht definiert
import { ref } from "vue";
export default {
setup() {
const title = ref("");
const one = ref(1);
const isValid = ref(true);
const foo = ref(null);
}
};
Im vorherigen Beispiel ist unser Titel vom Typ String. Um die Eigenschaft reaktiv zu machen, wählen wir ref (). Wenn der folgende Code Ihnen einige Fragen verursacht, machen Sie sich keine Sorgen, ich hatte die gleichen Fragen.
import { ref } from "vue";
export default {
setup() {
const title = ref("Hello, Vue 3!");
setTimeout(() => {
title.value = "New Title";
}, 5000);
return { title };
}
};
Warum verwenden wir const, wenn sich der Titel ändert? Warum nicht let verwenden? Wenn Sie Titel auf die Konsole drucken, wird möglicherweise Hello, Vue 3! Erwartet. Stattdessen wird ein Objekt angezeigt:
{_isRef: true}
value: (...)
_isRef: true
get value: ƒ value()
set value: ƒ value(newVal)
__proto__: Object
Die Funktion ref () nimmt ein Argument und gibt ein reaktives und veränderliches ref-Objekt zurück. Das Ref-Objekt hat eine Eigenschaft, value, die auf das Argument verweist. Dies bedeutet, dass Sie title.value verwenden müssen, wenn Sie den Wert abrufen oder ändern möchten. Da dies ein Objekt ist, das sich nicht ändert, habe ich es als const deklariert.
REF anrufen
Die nächste Frage ist, warum wir title.value in der Vorlage nicht aufrufen.
<template>
<h1>{{ title }}</h1>
</template>
Wenn Ref als Eigenschaft im Renderkontext (das von der Funktion setup () zurückgegebene Objekt) zurückgegeben wird und in der Vorlage referenziert wird, gibt Ref automatisch einen Wert zurück. Sie müssen der Vorlage keinen Wert hinzufügen.
Berechnete Eigenschaften funktionieren auf die gleiche Weise. In der Funktion setup () werden sie als .value bezeichnet.
REAKTIV
Wir haben gerade gesehen, wie ref () verwendet werden kann, um Eigenschaften einfacher Typen reaktiv zu machen. Was ist, wenn wir ein reaktives Objekt erstellen möchten? Wir könnten immer noch ref () verwenden, aber unter der Haube wird Vue reactive () verwenden, also bleibe ich bei reactive ().
Andererseits funktioniert reactive () nicht mit primitiven Typen. Die Funktion reactive () nimmt ein Objekt und gibt den reaktiven Proxy des Originals zurück. Dies entspricht .observable () in Vue 2, und dieser Funktionsname wurde geändert, um Verwechslungen mit Observablen in RxJS zu vermeiden.
import { reactive } from "vue";
export default {
setup() {
const data = reactive({
title: "Hello, Vue 3"
});
return { data };
}
};
Der Hauptunterschied besteht darin, wie wir auf das reaktive Objekt in der Vorlage verweisen. Im vorherigen Beispiel sind Daten ein Objekt, das eine Titeleigenschaft enthält. Sie müssen in der Vorlage wie folgt darauf verweisen - data.title:
<template>
<h1>{{ data.title }}</h1>
</template>
<script>
import { ref } from "vue";
export default {
setup() {
const data = ref({
title: "Hello, Vue 3"
});
return { data };
}
};
</script>
Unterschied zwischen REF und REACTIVE in einer Komponente
Basierend auf dem, was wir besprochen haben, scheint sich die Antwort zu bieten? Wir verwenden ref () für einfache Typen und reactive () für Objekte. Als ich anfing, Komponenten zu erstellen, stellte sich heraus, dass dies immer nicht der Fall ist, und in der Dokumentation heißt es:
Der Unterschied zwischen der Verwendung von ref und reaktiv kann in gewissem Maße mit dem Schreiben von Standardprogrammlogik in JavaScript vergleichbar sein.
Ich dachte über diesen Satz nach und kam zu den folgenden Schlussfolgerungen. Als die Anwendung wuchs, erhielt ich die folgenden Eigenschaften:
export default {
setup() {
const title = ref("Hello, World!");
const description = ref("");
const content = ref("Hello world");
const wordCount = computed(() => content.value.length);
return { title, description, content, wordCount };
}
};
In JavaScript würde ich verstehen, dass dies alles Eigenschaften meiner Seite sind. In diesem Fall würde ich sie in einem Seitenobjekt gruppieren. Warum nicht jetzt dasselbe tun?
<template>
<div class="page">
<h1>{{ page.title }}</h1>
<p>{{ page.wordCount }}</p>
</div>
</template>
<script>
import { ref, computed, reactive } from "vue";
export default {
setup() {
const page = reactive({
title: "Hello, World!",
description: "",
content: "Hello world",
wordCount: computed(() => page.content.length)
});
return { page };
}
};
</script>
Dies ist meine Herangehensweise an Ref oder Reactive, aber es wäre schön, Ihre Meinung zu kennen. Machst du das gleiche Vielleicht ist das nicht der richtige Ansatz? Bitte kommentieren.
Kompositionslogik
Sie können nichts falsch machen, wenn Sie ref () oder reactive () in Ihren Komponenten verwenden. Beide Funktionen erstellen reaktive Daten. Wenn Sie wissen, wie Sie in Ihrer setup () -Funktion und Ihren Vorlagen darauf zugreifen können, gibt es kein Problem.
Wenn Sie mit dem Schreiben von Kompositionsfunktionen beginnen, müssen Sie den Unterschied verstehen. Ich verwende Beispiele aus der RFC-Dokumentation, da einige die Nuancen gut veranschaulichen.
Sie müssen eine Logik zum Verfolgen der Mausposition erstellen. Sie sollten diese Logik bei Bedarf auch in jeder Komponente verwenden können. Sie erstellen eine Kompositionsfunktion, die die x- und y-Koordinaten verfolgt und diese dann an den Clientcode zurückgibt.
import { ref, onMounted, onUnmounted } from "vue";
export function useMousePosition() {
const x = ref(0);
const y = ref(0);
function update(e) {
x.value = e.pageX;
y.value = e.pageY;
}
onMounted(() => {
window.addEventListener("mousemove", update);
});
onUnmounted(() => {
window.removeEventListener("mousemove", update);
});
return { x, y };
}
Wenn Sie diese Logik in einer Komponente verwenden und diese Funktion aufrufen möchten, zerstören Sie das zurückgegebene Objekt und geben Sie die x- und y-Koordinaten an die Vorlage zurück.
<template>
<h1>Use Mouse Demo</h1>
<p>x: {{ x }} | y: {{ y }}</p>
</template>
<script>
import { useMousePosition } from "./use/useMousePosition";
export default {
setup() {
const { x, y } = useMousePosition();
return { x, y };
}
};
</script>
Dies funktioniert, aber wenn Sie sich nach dem Betrachten der Funktion entscheiden, ein Positionsobjekt anstelle von x und y umzugestalten und zurückzugeben:
import { ref, onMounted, onUnmounted } from "vue";
export function useMousePosition() {
const pos = {
x: 0,
y: 0
};
function update(e) {
pos.x = e.pageX;
pos.y = e.pageY;
}
// ...
}
Das Problem bei diesem Ansatz besteht darin, dass der Client der Kompositionsfunktion immer einen Verweis auf das zurückgegebene Objekt haben muss, damit die Reaktivität bestehen bleibt. Dies bedeutet, dass wir das Objekt nicht zerstören oder den Spread-Operator anwenden können:
//
export default {
setup() {
// !
const { x, y } = useMousePosition();
return {
x,
y
};
// !
return {
...useMousePosition()
};
//
// `pos` , x y : `pos.x` `pos.y`
return {
pos: useMousePosition()
};
}
};
Dies bedeutet jedoch nicht, dass wir in diesem Fall nicht reaktiv verwenden können. Es gibt eine toRefs () -Funktion, die ein reaktives Objekt in ein einfaches Objekt konvertiert, dessen jede Eigenschaft die Referenz der entsprechenden Eigenschaft des ursprünglichen Objekts ist.
function useMousePosition() {
const pos = reactive({
x: 0,
y: 0
});
// ...
return toRefs(pos);
}
// x & y ref!
const { x, y } = useMousePosition();
Daher sind beim Erstellen von Kompositionsfunktionen einige Aspekte zu berücksichtigen. Wenn Sie verstehen, wie der Client-Code mit Ihren Funktionen funktioniert, ist alles in Ordnung.
GESAMT
Als ich anfing, die Kompositions-API zu verwenden, war ich verwirrt über die Frage, wann ref () und wann reaktiv () anzuwenden ist. Vielleicht mache ich es immer noch nicht richtig und bis mir jemand das sagt, bleibe ich bei diesem Ansatz. Hoffentlich hat es geholfen, einige der Probleme zu klären, und würde gerne Ihr Feedback hören.
Viel Spaß beim Codieren