Home >Web Front-end >Vue.js >Share an extremely comfortable Vue page keeping solution

Share an extremely comfortable Vue page keeping solution

藏色散人
藏色散人forward
2023-04-10 16:29:031441browse

This article brings you relevant knowledge about Vue. It mainly shares with you an extremely comfortable Vue page keeping solution. There are code examples. Friends who are interested can take a look below. I hope everyone has to help.

In order to make page keep-alive more stable, what do you do?

I implemented it with one line of configuration

Share an extremely comfortable Vue page keeping solution

Vue page keep-alive means that after the user leaves the current page, he can Restore the state of the last viewed page. This technology allows users to enjoy a smoother and more natural browsing experience without being disturbed by cumbersome operations.

Why do we need to keep the page alive?

Page keeping alive can improve the user experience. For example, when the user jumps from a table page with pagination ([Page A]) to the data details page ([Page B]), and after viewing the data, when the user returns from [Page B] to [Page A] , if there is no page keep alive, [Page A] will reload and jump to the first page, which will make users very annoyed because they need to re-select the page and data. Therefore, using page keep-alive technology, when the user returns to [Page A], the previously selected page number and data can be restored, making the user experience smoother.

How to keep the page alive?

State Storage

This solution is the most intuitive. The principle is to manually store the state that needs to be kept alive before leaving [Page A]. State can be stored to LocalStore, SessionStore, or IndexedDB. In the onMounted hook of the [Page A] component, check whether the previous state exists, and if so, restore the state from external storage.

What is the problem?

  • Waste of mind (trouble/worry). The problem with this solution is that you need to know clearly when writing the component to store the state when jumping to certain pages.
  • Unable to resolve child component state. You can also save the status of page components in page components, but how to save sub-components. It is impossible to maintain all sub-component states in the page component, because such a structure is not reasonable.

Component caching

Using Vue's built-in components<keepalive></keepalive>Cache the dynamic switching component wrapped in it (also It’s <component></component> component). <keepalive></keepalive>When wrapping dynamic components, inactive components will be cached instead of destroying them. When a component is toggled in <keepalive></keepalive>, the activated and deactivated lifecycle hooks replace mounted and unmountedHook. The most important thing is that <keepalive></keepalive> applies not only to the root node of the wrapped component, but also to its descendant nodes.

<keepalive></keepalive>Paired with vue-router, the page can be kept alive. The implementation code is as follows:

<template>
  <RouterView v-slot="{ Component }">
    <KeepAlive>
      <component :is="Component"/>
    </KeepAlive>
  </RouterView>
</template>

What’s the problem? ?

  • Page keepalive is inaccurate. Although the above method achieves page keep-alive, it cannot meet production requirements. For example: [Page A] is the application homepage, [Page B] is the data list page, and [Page C] is the data details page. The moving line for users to view data details is: [Page A]->[Page B]->[Page C]. In this moving line, [Page B]->[Page C] needs to be cached [ Page B], when changing from [Page C]->[Page B], you need to restore [Page B] from it. However, when [Page B] -> [Page A], there is no need to cache [Page B]. The above method cannot achieve such a configuration.

Best Practice

The most ideal way to keep alive is to achieve on-demand page keepalive through simple configuration without invading the component code.

[No intrusion into component code] This rule eliminates the implementation of the first method. The second method [component caching] is only defeated by [on-demand page keep-alive]. Then transform the second way, by configuring on-demand keep-alive on the routing configuration of router, and then provide a read configuration combined with <keepalive></keepalive>includeAttributes are enough.

Routing configuration

src/router/index.ts

import useRoutersStore from &#39;@/store/routers&#39;;

const routes: RouteRecordRaw[] = [
  {
    path: &#39;/&#39;,
    name: &#39;index&#39;,
    component: () => import(&#39;@/layout/index.vue&#39;),
    children: [
      {
        path: &#39;/app&#39;,
        name: &#39;App&#39;,
        component: () => import(&#39;@/views/app/index.vue&#39;),
      },
      {
        path: &#39;/data-list&#39;,
        name: &#39;DataList&#39;,
        component: () => import(&#39;@/views/data-list/index.vue&#39;),
        meta: {
          // 离开【/data-list】前往【/data-detail】时缓存【/data-list】
          leaveCaches: [&#39;/data-detail&#39;],
        }
      },
      {
        path: &#39;/data-detail&#39;,
        name: &#39;DataDetail&#39;,
        component: () => import(&#39;@/views/data-detail/index.vue&#39;),
      }
    ]
  }
];

router.beforeEach((to: RouteLocationNormalized, from: RouteLocationNormalized, next: NavigationGuardNext) => {
  const { cacheRouter } = useRoutersStore();
  cacheRouter(from, to);
  next();
});

Keep-alive component storage

src/stroe /router.ts

import { RouteLocationNormalized } from &#39;vue-router&#39;;

const useRouterStore = defineStore(&#39;router&#39;, {
  state: () => ({
    cacheComps: new Set<string>(),
  }),
  actions: {
    cacheRouter(from: RouteLocationNormalized, to: RouteLocationNormalized) {
      if(
        Array.isArray(from.meta.leaveCaches) && 
        from.meta.leaveCaches.inclued(to.path) && 
        typeof from.name === &#39;string&#39;
      ) {
        this.cacheComps.add(form.name);
      }
      if(
        Array.isArray(to.meta.leaveCaches) && 
        !to.meta.leaveCaches.inclued(from.path) && 
        typeof to.name === &#39;string&#39;
      ) {
        this.cacheComps.delete(to.name);
      }
    },
  },
  getters: {
    keepAliveComps(state: State) {
      return [...state.cacheComps];
    },
  },
});

Page cache

src/layout/index.vue

<template>
  <RouterView v-slot="{ Component }">
    <KeepAlive :include="keepAliveComps">
      <component :is="Component"/>
    </KeepAlive>
  </RouterView>
</template>

<script setup>
import { storeToRefs } from &#39;pinia&#39;;
import useRouterStore from &#39;@/store/router&#39;;

const { keepAliveComps } = storeToRefs(useRouterStore());
</script>

TypeScript提升配置体验

import &#39;vue-router&#39;;

export type LeaveCaches = string[];

declare module &#39;vue-router&#39; {
  interface RouteMeta {
    leaveCaches?: LeaveCaches;
  }
}

该方案的问题

  • 缺少通配符处理/*/**/index
  • 无法缓存/preview/:address这样的动态路由。
  • 组件名和路由名称必须保持一致。

总结

通过<routerview v-slot="{ Component }"></routerview>获取到当前路由对应的组件,在将该组件通过<component :is="Component"></component>渲染,渲染之前利用<keepalive :include="keepAliveComps"></keepalive>来过滤当前组件是否需要保活。 基于上述机制,通过简单的路由配置中的meta.leaveCaches = [...]来配置从当前路由出发到哪些路由时,需要缓存当前路由的内容。【推荐学习:《vue.js视频教程》】

如果大家有其他保活方案,欢迎留言交流哦!

The above is the detailed content of Share an extremely comfortable Vue page keeping solution. For more information, please follow other related articles on the PHP Chinese website!

Statement:
This article is reproduced at:juejin.im. If there is any infringement, please contact admin@php.cn delete