【问题标题】:VUE 3 Force unmount when deactivatedVUE 3 停用时强制卸载
【发布时间】:2021-10-29 21:36:31
【问题描述】:

我有 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: {},
};

你认为最好的做法是什么?

【问题讨论】:

    标签: javascript vue.js vue-router vuejs3 vue-router4


    【解决方案1】:

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

    当一个组件在启动后从 keep-alive 中排除,然后在达到 max 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 找不到动态排除的组件。

    【讨论】:

      【解决方案2】:

      有条件的keep-alive

      您可以通过keepAliveExcludes 反应集将子路由添加/删除到keep-alive's exclude propertyprovide 方法。将 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绑定到&lt;keep-alive&gt;.exclude

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

      在子路由中,injectkeepAliveExcludes,并在需要时使用组件名称(例如,通过复选框)调用其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 那样复杂。

      在应用模板中,在&lt;keep-alive&gt;.exclude中指定组件的名称(必须与组件声明中的name prop匹配):

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

      demo 2

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 2015-03-18
        • 1970-01-01
        • 2021-05-26
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2019-07-17
        相关资源
        最近更新 更多