简体   繁体   中英

How to destroy a VueJS component that is being cached by <keep-alive>

I have a Vue component that's kept alive using Vue's element for caching purposes. However, the problem I am having right now is that once I sign out of one account and create a new account on my Vue application, the component I'm "keeping alive" is being reflected for the new user (which obviously isn't relevant for the new user).

As a result, I want to destroy that component once the user signs out. What is the best way to go about this?

I've managed to solve my issue in the following way. Essentially, if the user is logged in, keep the dashboard alive. Else, don't keep the dashboard alive. I check if the user is logged in or out every time the route changes by "watching" the route (see below). If you are reading this and have a more elegant solution - I'd love to hear it.

The following is the code for my root component

<template>
    <div id="app">
        <!-- if user is logged in, keep dashboard alive -->
        <keep-alive
            v-bind:include="[ 'dashboard' ]"
            v-if="isLoggedIn">
            <router-view></router-view>
        </keep-alive>
        <!-- otherwise don't keep anything alive -->
        <router-view v-else></router-view>
    </div>
</template>

<script>
    import firebase from "firebase";

    export default {
        name: 'app',
        data() {
            return {
                isLoggedIn: false // determines if dashboard is kept alive or not
            }
        },
        watch: {
            $route (to, from){ // if the route changes...
                if (firebase.auth().currentUser) { // firebase returns null if user logged out
                    this.isLoggedIn = true;
                } else {
                    this.isLoggedIn = false;
                }
            }
        }
    }
</script>

I had the same problem and I solved it by using an array of cached components and bus event.

Here is my HTML keep-alive App.vue:

<keep-alive :include="cachedComponents">
  <router-view></router-view>
</keep-alive>

Here is what I'm doing in the created() life cycle:

   created() {
      // Push Home component in cached component array if it doesn't exist in the array
      if (!this.cachedComponents.includes('Home')) {
        this.cachedComponents.push('Home')
      }

      // Event to remove the components from the cache
      bus.$on('clearCachedComponents', (data) => {
        // If the received component exist
        if (this.cachedComponents.includes(data)) {
          // Get the index of the component in the array
          const index = this.cachedComponents.indexOf(data)
          // Remove it from the array
          this.cachedComponents.splice(index, 1)
        }
      })
    }

And inside another component just trigger the event and send the component to remove in parameter.

Another.vue

bus.$emit('clearCachedComponents', 'Home')

If you don't know how to make a bus event there are lot of tutorials on the internet like this to do that. But bus event is my way to do that and you can use everything you want like a child emitter or Vuex. That I want to show is to use an array of components to manage your cache. All you have to do is to add or remove your components in the array.

for anyone looking for a solution that destroys the cache

in my case I was using this in a logout route, replace router.app with this.$root in Vue instances and the $children index/nesting may differ for your app

setTimeout(() => {
    var d = [];
    for(var vm of router.app.$children[0].$children) {
        if(vm._inactive === true)
            d.push(vm);
    }
    for(var vm of d) {
        vm.$destroy();
    }
});

If your problem is that the component is still holding the old user's data, the only option is resetting it with an internal reset function, which reloads the data for the new user one way or another.

See: http://jsfiddle.net/paolomioni/hayskdy8/

var Home = Vue.component('Home', {
  template: `<div><h1>{{ title }}</h1>
  <input type="button" value="click to change text" v-on:click="title = Math.random()"">
  <input type="button" value="click to reset component" v-on:click="reset"></div>`,
  data: () => {
    return {
      title: 'BBB'
    }
  },
  methods: {
    reset() {
      this.title = 'BBB'
    }
  }
});

In the fiddle, click on the button "change text" to change the text: if you click the checkbox twice to switch view and back again, you will see that the number you've generated is still kept in memory. If you click on the "reset" button, it will be reset to its initial state. You need to implement the reset method on your component and call it programmaticaly when the user logs out or when the new user logs in.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM