最新消息:雨落星辰是一个专注网站SEO优化、网站SEO诊断、搜索引擎研究、网络营销推广、网站策划运营及站长类的自媒体原创博客

javascript - How can I tell if a Vue component is unmounted to prevent async function accessing unmounted component's da

programmeradmin6浏览0评论

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 using clearTimeout instead to cancel the timer within your beforeDestroy hook. – skirtle Commented Jan 10, 2020 at 13:35
Add a ment  | 

3 Answers 3

Reset to default 3

Here 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", () => {
      //...
    })
  }

与本文相关的文章

发布评论

评论列表(0)

  1. 暂无评论