VUE 3 停用时强制卸载

VUE 3 Force unmount when deactivated

我有 VUE 应用程序,它在路由器中使用 keep-alive 方法。许多页面只需要加载一次,但某些特定页面需要在每次激活时重新加载。

<template>
  <router-view v-slot="{ Component }">
    <keep-alive max="5">
      <component :is="Component" />
    </keep-alive>
  </router-view>
<template>

我想做的是 unmount 来自 keep-alive 缓存的页面组件 deactivated

/* this is the loaded component */
export default {
  setup() {
    const state=ref({})
    /*init and load data...*/
   
    onDeactivated(()=>{
     //unmount this component ???
    });
    
    return { state };
  },
  components: {},
};

您认为最佳做法是什么?

有条件的keep-alive

您可以 provide methods for child routes to add/remove themselves to keep-alive's exclude property 通过 keepAliveExcludes 反应集。将 ref 作为计算的 array 暴露给模板(exclude 属性需要 Array,而不是 Set):

// App.vue
import { provide, reactive, computed } from 'vue'

export default {
  setup() {
    const keepAliveExcludes = reactive(new Set())

    provide('keepAliveExcludes', {
      add: name => keepAliveExcludes.add(name),
      remove: name => keepAliveExcludes.delete(name),
    })

    return {
      keepAliveExcludes: computed(() => Array.from(keepAliveExcludes))
    }
  }
}

在应用程序模板中,将 keepAliveExcludes 绑定到 <keep-alive>.exclude:

<template>
  <router-view>
    <keep-alive :exclude="keepAliveExcludes">
      ...
    </keep-alive>
  </router-view>
</template>

在子路由中,inject keepAliveExcludes,并在需要时使用组件名称调用其 add/remove(例如,通过复选框):

<template>
  <h1>About</h1>
  <div>
    <label>Keep Alive
      <input type="checkbox" v-model="keepAlive">
    </label>
  </div>
</template>

<script>
import { ref, inject, watchEffect } from 'vue'

export default {
  name: 'About',
  setup() {
    const { add: addKeepAliveExclude, remove: removeKeepAliveExclude } = inject('keepAliveExcludes', {})

    const keepAlive = ref(true)
   
    watchEffect(() => {
      if (keepAlive.value) {
        removeKeepAliveExclude?.('About')
      } else {
        addKeepAliveExclude?.('About')
      }
    })

    return { keepAlive }
  },
}
</script>

demo 1

始终从 keep-alive

中排除

如果您需要 始终keep-alive 缓存中排除组件,您可以简单地静态设置组件名称,而无需 provide 的复杂性/inject 以上。

在应用程序模板中,在 <keep-alive>.exclude:

中指定组件名称(必须与组件声明中的 name 属性匹配)
<template>
  <router-view>
    <keep-alive exclude="About">
      ...
    </keep-alive>
  </router-view>
</template>

demo 2

@tony19 发布了一个很棒的答案,但由于 VUE 的一个可能错误(目前我使用 3.2.6),它有一些问题。

当一个组件在启动后被排除在keep-alive之外,然后在达到最大keep-alive组件后,VUE尝试删除不存在的排除组件。

这会导致错误并停止应用程序。有关错误的更多信息,请参见下文。

我的解决方案依赖于 tony19 令人兴奋的解决方案。

我没有在加载组件后排除它,而是在加载组件之前向路由器添加规则。

const routes = [
  /* ... */
  {
    path: "/about",
    name: "AboutPage",
    meta: { excludeKeepAlive: true },
    component: () => import('./../components/AboutPage.vue'),
  }
  /* ... */
];

然后在主APP中;

/* This is the main app */
export default {
  setup() {
    /* ... */
    const keepAliveExcludes = reactive(new Set());

    cont keepAliveExcluder= {
      add: name => keepAliveExcludes.add(name),
      remove: name => keepAliveExcludes.delete(name),
    }
   
    router.beforeEach((to, from, next) => {    
      if(to.meta?.excludeKeepAlive===true){      
        keepAliveExcluder.add(to.name);
      } 
      next();
     });
    /* ... */
   return {
      keepAliveExcludes: computed(() => Array.from(keepAliveExcludes))
    }
   }
}

有关错误的更多信息(可能是错误)

runtime-core.esm-bundler.js:2057

出现错误

Uncaught (in promise) TypeError: Cannot read property 'type' of undefined

VUE 找不到动态排除的组件。