core icon indicating copy to clipboard operation
core copied to clipboard

KeepAlive provide function to delete cache

Open xikeqian opened this issue 3 years ago • 5 comments

What problem does this feature solve?

We can open multiple tabs. The components corresponding to the tabs use the keepalive cache. We need to destroy the keepalive cache when closing the tabs to release the cache. We also know KeepAlive max property but that can't delete specified cache. hope expose keys and cache property in production

What does the proposed API look like?

hope expose keys and cache property in production or provide function to delete cache by key

xikeqian avatar May 31 '22 08:05 xikeqian

https://github.com/HcySunYang/rfcs/blob/keepalive-cache-management-and-match-rules/active-rfcs/0000-keepalive-cache-management-and-match-rules.md

#4339

lidlanca avatar Jun 01 '22 03:06 lidlanca

Has this PR passed? @lidlanca

xikeqian avatar Jun 06 '22 14:06 xikeqian

its been open for more than a year, I don't know what blocks it.

lidlanca avatar Jun 06 '22 20:06 lidlanca

maybe you can do it use KeepAlive.

If use router controll it, record route:

// record tabs
const pages = reactive([]);

// when route changed, record it
router.afterEach((to) => {
  const key = getKeyFromRoute(to);
  if (pages.find((tab) => tab.key === key)) {
    return;
  }
  pages.push({
    key,
    component: null,
  });
});

// calc key of the route
function getKeyFromRoute(route) {
  const keepAlive = route.meta.keepAlive ?? "path";

  return keepAlive === "path"
    ? route.path
    : keepAlive === "fullPath"
    ? route.fullPath
    : route.name;
}

then, render router view:


// render the router view
function setup() {
  // keepalive components name
  const includes = ref([]);

  // when tabs changed, calc the includes
  watch(
    () => pages,
    () => {
      // delay update, because of current component's onUnmounted callback
      requestIdleCallback(() => {
        includes.value = theme.pages
          .filter((tab) => tab.keepAlive)
          .map((tab) => `Route@${tab.key}`);
      });
    }
  );

  return () => (
    <RouterView>
      {{
        default: ({ Component, route }) => {
          if (!Component) return null;
          const key = getKeyFromRoute(route);
          // notice, use reactive var 'pages' in slots function maybe cause this slot duplicate render. 
          // should use other var to avoid it
          const tab = pages.find((tab) => key === tab.key);
          if (!tab) return null;

          // wrapper component name use key of route
          if (!tab.component) {
            tab.component = markRaw(
              defineComponent({
                name: `Route@${key}`,
                render: () => Component,
              })
            );
          }

          const RouterViewRender = tab.component;

          return (
            <KeepAlive include={includes.value}>
              <RouterViewRender />
            </KeepAlive>
          );
        },
      }}
    </RouterView>
  );
}

when close tab, delete tab from pages:

function close(tabIndex) {
  pages.slice(tabIndex, 1)
}

liuzw2579 avatar Aug 05 '22 15:08 liuzw2579

maybe you can do it use KeepAlive.

If use router controll it, record route:

// record tabs
const pages = reactive([]);

// when route changed, record it
router.afterEach((to) => {
  const key = getKeyFromRoute(to);
  if (pages.find((tab) => tab.key === key)) {
    return;
  }
  pages.push({
    key,
    component: null,
  });
});

// calc key of the route
function getKeyFromRoute(route) {
  const keepAlive = route.meta.keepAlive ?? "path";

  return keepAlive === "path"
    ? route.path
    : keepAlive === "fullPath"
    ? route.fullPath
    : route.name;
}

then, render router view:

// render the router view
function setup() {
  // keepalive components name
  const includes = ref([]);

  // when tabs changed, calc the includes
  watch(
    () => pages,
    () => {
      // delay update, because of current component's onUnmounted callback
      requestIdleCallback(() => {
        includes.value = theme.pages
          .filter((tab) => tab.keepAlive)
          .map((tab) => `Route@${tab.key}`);
      });
    }
  );

  return () => (
    <RouterView>
      {{
        default: ({ Component, route }) => {
          if (!Component) return null;
          const key = getKeyFromRoute(route);
          // notice, use reactive var 'pages' in slots function maybe cause this slot duplicate render. 
          // should use other var to avoid it
          const tab = pages.find((tab) => key === tab.key);
          if (!tab) return null;

          // wrapper component name use key of route
          if (!tab.component) {
            tab.component = markRaw(
              defineComponent({
                name: `Route@${key}`,
                render: () => Component,
              })
            );
          }

          const RouterViewRender = tab.component;

          return (
            <KeepAlive include={includes.value}>
              <RouterViewRender />
            </KeepAlive>
          );
        },
      }}
    </RouterView>
  );
}

when close tab, delete tab from pages:

function close(tabIndex) {
  pages.slice(tabIndex, 1)
}

This seems to work by redefine component name , let me try.

xikeqian avatar Aug 08 '22 00:08 xikeqian