preamble
In Ouyang's last postThis should be the most detailed explanation of Vue 3.5 on the net!The article has a number of students who are interested in Vue 3.5's newonWatcherCleanup
It's a bit confusing, this added API seems to be the same as thewatch API
The third parameter of the callbackonCleanup
The functionality seems to be duplicated. Today's post is about the addition of theonWatcherCleanup
Scenarios for the use of functions:Wrapping a fetch function for automatic canceling
。
Follow the public number: [Front-end Ouyang], give yourself a chance to advance vue
The third parameter of the watch callback, onCleanup.
Some students may not be awarewatch
The third parameter of the callbackonCleanup
We'll start with a demo, the code is as follows:
watch(id, (value, oldValue, onCleanup) => {
("do something");
onCleanup(() => {
("cleanup");
});
});
watch
The first two parameters of the callback should be familiar to you, which arevalue
The new value.oldValue
Old value.
Third parameteronCleanup
You may not usually use it much, it's a callback function, when thewatch
is executed after the value of the component changes or before the component is destroyed.onCleanup
incoming callbacks.
In the demo above is the variableid
Triggered on changeonCleanup
The pullback in, and thusconsole
printable"cleanup"
string. Or maybe the component it's in triggers before it's destroyed.onCleanup
The pullback in, and thusconsole
printable"cleanup"
String.
Then we're inonCleanup
What can I do in it?
The answer is that it's possible to clean up side effects, such as in overwatch withsetInterval
Initialize a timer. Then we can initialize the timer in theonCleanup
callback to clean up the timer without having to go to the component'sbeforeUnmount
The hook function goes to unify the cleanup.
onWatcherCleanup
function (math.)
onWatcherCleanup
The role of the function is the same as that of thewatch
The third parameter of the callbackonCleanup
Pretty much, also whenwatch
is executed after the value of the component changes or before the component is destroyed.onWatcherCleanup
incoming callbacks.
The usage is also very simple, the code is as follows:
import { watch, onWatcherCleanup } from "vue";
watch(id, () => {
("do something");
onWatcherCleanup(() => {
("cleanup");
});
});
As you can see from the code aboveonWatcherCleanup
The usage is actually similar to that ofwatch
The third parameter of the callbackonCleanup
Pretty much the same, the difference is that hereonWatcherCleanup
is imported from vue.
In addition to the difference of importing from vue, there's also a difference betweenonWatcherCleanup
not just inwatch
can be used in thewatchEffect
The same can be used in For example, something like the following:
watchEffect(() => {
("do something in watchEffect", );
onWatcherCleanup(() => {
("cleanup watchEffect");
});
});
As in the previous example, the code aboveid
or when the component is destroyed.onWatcherCleanup
function in thePrint.
onWatcherCleanup
function is imported from vue, then this means that theonWatcherCleanup
Function calls can be written anywhere, as long as they end up in the function's hierarchy of calls still in thewatch
orwatchEffect
in the callback is fine.
Using this feature above we can use theonWatcherCleanup
touch baseonCleanup
Things that can't be done, e.g., encapsulating an automatedcancel
(used form a nominal expression)fetch
function.
Wrapping the fetch function for autocancel
Before we get to that let's find out how tocancel
anfetch
function.
Here's what's involvedAbortController
Interface.AbortController
Interface represents a controller object that allows you to abort one or more Web requests as needed.
Here's one.cancel
Cancel a request demo with the following code:
const controller = new AbortController();
const res = await fetch(url, {
...options,
signal: ,
});
setTimeout(() => {
();
}, 500);
first usingnew AbortController()
Create a controller objectcontroller
。
includedReturns aAbortSignal object instance that can be used to communicate with or abort an asynchronous operation.
In our case putact as
signal
option is passed directly to the fetch function.
Finally, there is the possibility of using()
Cancel the fetch request, in the above demo it is if the request is not completed for more than 500ms, then execute the()
Cancel the fetch request out.
With this knowledge in mind, let's take a look at the use of the "Automaticcancel
(used form a nominal expression)fetch
function", the code is as follows:
<script setup lang="ts">
import { watch, ref, watchEffect, onWatcherCleanup } from "vue";
import myFetch from "./myFetch";
const id = ref(1);
const data = ref(null);
watch(id, async () => {
const res = await myFetch(`http://localhost:3000/api/${}`, {
method: "GET",
});
(res);
= res;
});
</script>
<template>
<p>data is: {{ data }}</p>
<button @click="id++">id++</button>
</template>
In the above example use thewatch
Listened to the variableid
, in the callback of the listener will use the encapsulatedmyFetch
Function request interface.
The above example should be often encountered by you in your daily life, if theid
value changes quickly, but the server-side interface request takes 2 seconds to complete, at which point we expect that only the lastid
The requests triggered by a change in the value of the
If there is a change in themyFetch
The component is destroyed during the request, at which point we also expect the request cancel to be canceled.
Before Vue 3.5 it was a pain in the ass to try to implement these two requirements above, but with Vue 3.5'sonWatcherCleanup
It is very easy after the function.
This one is encapsulated automaticallycancel
(used form a nominal expression)fetch
function.The file code is as follows:
import { getCurrentWatcher, onWatcherCleanup } from "vue";
export default async function myFetch(url: string, options: RequestInit) {
const controller = new AbortController();
if (getCurrentWatcher()) {
onWatcherCleanup(() => {
();
});
}
const res = await fetch(url, {
...options,
signal: ,
});
let json;
try {
json = await ();
} catch (error) {
json = {
code: 500,
message: "JSON format error",
};
}
return json;
}
due toonWatcherCleanup
function is imported from vue, then we can add it to our own wrappedmyFetch
function to import and use him.
existonWatcherCleanup
function's callback we execute the()
As mentioned earlier whenwatch
orwatchEffect
before the callback is executed or before the component is uninstalled.onWatcherCleanup
Registered callbacks. What we have here is themyFetch
Yes, it is.watch
which, of course, triggers a call to theonWatcherCleanup
Registered callbacks.
existonWatcherCleanup
is executed in the callback of the()
We talked earlier about the implementation of()
It will then cancel the fetch function being requested to cancel.
It's as simple as that to fulfill the first two requirements:
Demand One:in the event thatid
value changes quickly, but the server-side interface request takes 2 seconds to complete, at which point we expect that only the lastid
The requests triggered by a change in the value of theHere's a gif of the variable id being modified multiple times in a short period of time:
As you can see from the gif above only the last request was completed, all other requests were canceled.
Demand II:If there is a change in themyFetch
The component is destroyed during the request, at which point we also expect the request cancel to be canceled.Here's a gif of the component uninstalled:
As you can see from the above figure, the component is requesting data from the server when it is uninstalled, and the request is automatically canceled at this point.
The attentive little ones have found a great deal of interest in themyFetch
function.onWatcherCleanup
function is wrapped around agetCurrentWatcher
judgment, the code is as follows:
import { getCurrentWatcher, onWatcherCleanup } from "vue";
export default async function myFetch(url: string, options: RequestInit) {
// ...an omission
if (getCurrentWatcher()) {
onWatcherCleanup(() => {
();
});
}
// ...an omission
}
When the value of the watch or watchEffect listener has changedonWatcherCleanup
callback is triggered, so theonWatcherCleanup
is triggered by the watch or watchEffect in which it is executed.
in the event thatonWatcherCleanup
is not executed in the watch or watchEffect callback, then of course theonWatcherCleanup
The callbacks in will also never be executed.
Some of you may have questions about what you have here.onWatcherCleanup
Yes, it is.myFetch
and not in the watch or watchEffect callbacks?
The answer.myFetch
function is executed in watch.myFetch
Then go ahead and executeonWatcherCleanup
。
(indicates contrast)getCurrentWatcher()
The function then returns the currentCallbacks being executedor watchEffect, if the currentmyFetch
is not executed in the watch or watchEffect callback, then thegetCurrentWatcher()
The return value of the function is null, so there's no need to perform theonWatcherCleanup
function now.
Lastly, it's worth mentioning thatonWatcherCleanup
It can't be executed after await, like in the following code:
import { getCurrentWatcher, onWatcherCleanup } from "vue";
export default async function myFetch(url: string, options: RequestInit) {
const controller = new AbortController();
const res = await fetch(url, {
...options,
signal: ,
});
let json;
try {
json = await ();
} catch (error) {
json = {
code: 500,
message: "JSON format error",
};
}
// ❌ Incorrectly written
if (getCurrentWatcher()) {
onWatcherCleanup(() => {
();
});
}
return json;
}
In the code above we've set theonWatcherCleanup
The call is placed in theawait fetch()
This way of writingonWatcherCleanup
registeredCallbacks are not executed。
Why is it in theawait
backonWatcherCleanup
What about registered callbacks that never execute?
The answer is that js's await is equivalent to registering a callback function to execute the post-await code, and then executing that callback function when the await wait is over, thus executing the post-await code.
await and the code before it is indeed executed in the watch callback, where we have theonWatcherCleanup
It is the code after the await, the code after the await is executed in a new callback, that is, the watch "callback" in the "callback" execution.
(coll.) fail (a student)onWatcherCleanup
execution no longer knows who the currently executing watch callback is, so theonWatcherCleanup
The callbacks are also not registered. When a variable in watch is modified or when a component is uninstalled theonWatcherCleanup
Registered callbacks are never executed.
summarize
(coll.) fail (a student)watch
orwatchEffect
listener's variables are modified, and when the component is uninstalled, it goes to execute their callbacks using theonWatcherCleanup
registered callback function. AndonWatcherCleanup
is imported from vue, making mine executable anywhere!onWatcherCleanup
function. Using these two features we can encapsulate a fetch function that automatically cancels.
Follow the public number: [Front-end Ouyang], give yourself a chance to advance vue
Also Ouyang wrote an open source ebookvue3 Compilation Principles Revealed, reading this book can give you a qualitative improvement in your knowledge of vue compilation. This book is accessible to beginner and intermediate front-ends and is completely free, just asking for a STAR.