Please see this minimum example
import Vue from 'vue';
Vue.extend({
data() {
return {
name: 'James',
};
},
methods: {
greet() {
setTimeout(() => {
const ponentIsUnmounted = ???; // How do I tell if ponent is unmounted?
if (!ponentIsUnmounted) {
console.log(this.name);
}
}, 300);
},
},
});
As you can see, I have a ponent with an async function, it will be triggered after 300ms when you called it, by that time, the Vue ponent might be unmounted.
I think I can do this by storing a flag in the global via Lodash's uniqueID()
function to create a unique ID at mounted()
and beforeDestroyed()
.
Is there another easyier way to do that?
Please see this minimum example
import Vue from 'vue';
Vue.extend({
data() {
return {
name: 'James',
};
},
methods: {
greet() {
setTimeout(() => {
const ponentIsUnmounted = ???; // How do I tell if ponent is unmounted?
if (!ponentIsUnmounted) {
console.log(this.name);
}
}, 300);
},
},
});
As you can see, I have a ponent with an async function, it will be triggered after 300ms when you called it, by that time, the Vue ponent might be unmounted.
I think I can do this by storing a flag in the global via Lodash's uniqueID()
function to create a unique ID at mounted()
and beforeDestroyed()
.
Is there another easyier way to do that?
Share asked Jan 10, 2020 at 12:31 JosephJoseph 4,7258 gold badges40 silver badges80 bronze badges 4- Which ponent and why will be unmounted? – Justice47 Commented Jan 10, 2020 at 12:37
-
unsure what you are trying to do here but you might be able to utilize
clearTimeout()
which is a native javascript function – Flame Commented Jan 10, 2020 at 12:39 - I'm performing an async function, the async function will access the ponent's data, in that 300ms time, the ponent might be unmounted by other people, the async action what I want to do is actually debounce, but I simplify the question with a setTimeout – Joseph Commented Jan 10, 2020 at 12:42
-
Not sure you need a global flag for this. You can just set a boolean flag/property on the ponent instance itself and check that within your timer callback function. Vue already has a private property called
_isBeingDestroyed
that I tend to use for this purpose but it is private so use it at your own risk. If possible I'd suggest usingclearTimeout
instead to cancel the timer within yourbeforeDestroy
hook. – skirtle Commented Jan 10, 2020 at 13:35
3 Answers
Reset to default 3Here is what I just used and it worked great.
When you create the timeout, store the ID on this
. Then on beforeDestroy
, call clearTimeout
with the ID. Even if you manually cancel the timeout beforehand, clearTimeout
will not fail.
<script>
export default {
created() {
this.timeoutId = setTimeout(() => {}, 1000)
},
beforeDestroy() {
clearTimeout(this.timeoutId)
}
}
</script>
No need to set it in the data
property, as it isn't reactive.
I think that it would be best if you can control the timeout (using clearTimeout()
, for example, as suggested on the ments). In your case, as you're using a debounce
, depending on what lib you're using, you might not have that control.
In this case, one suggestion is to mix Node.contains
with vm.$el
. As follows:
export default {
methods: {
greet() {
const isUnmounted = !document.body.contains(this.$el)
}
}
}
Other alternative is to use destroyed
lifecycle to control this state internally.
I've provided a guiding example that might help you: https://codesandbox.io/s/smoosh-frost-fdisj.
Hope it helps!
You can use the beforeDestroy event like below :
mounted() {
this.$once("hook:beforeDestroy", () => {
//...
})
}