>  기사  >  웹 프론트엔드  >  매우 편안한 Vue 페이지 유지 솔루션을 공유하세요

매우 편안한 Vue 페이지 유지 솔루션을 공유하세요

藏色散人
藏色散人앞으로
2023-04-10 16:29:031369검색

이 기사는 Vue에 대한 관련 지식을 제공합니다. 주로 매우 편안한 Vue 페이지 유지 솔루션을 공유합니다. 관심 있는 친구가 도움이 되기를 바랍니다.

페이지 연결 유지를 보다 안정적으로 만들기 위해 무엇을 합니까?

한 줄의 구성으로 구현했습니다

매우 편안한 Vue 페이지 유지 솔루션을 공유하세요

Vue 페이지 연결 유지는 사용자가 현재 페이지를 떠난 후 다시 돌아올 때 마지막으로 탐색한 페이지의 상태를 복원할 수 있다는 의미입니다. 이 기술을 통해 사용자는 번거로운 작업에 방해받지 않고 보다 부드럽고 자연스러운 탐색 경험을 즐길 수 있습니다.

페이지를 계속 유지해야 하는 이유는 무엇인가요?

페이지를 활성 상태로 유지하면 사용자 경험이 향상될 수 있습니다. 예를 들어, 페이지 매김이 있는 테이블 페이지([페이지 A])에서 데이터 상세 페이지([페이지 B])로 점프한 후, 데이터를 조회한 후 [페이지 B]에서 [페이지 A]로 되돌아오는 경우 ] 페이지 유지가 없으면 [페이지 A]가 다시 로드되어 첫 번째 페이지로 이동합니다. 이는 페이지와 데이터를 다시 선택해야 하기 때문에 사용자를 매우 짜증나게 합니다. 따라서 페이지 연결 유지 기술을 사용하면 사용자가 [페이지 A]로 돌아갈 때 이전에 선택한 페이지 번호와 데이터가 복원되어 사용자 경험이 더욱 원활해집니다.

페이지를 활성 상태로 유지하는 방법은 무엇입니까?

State Storage

이 솔루션은 [페이지 A]를 떠나기 전에 유지해야 하는 상태를 수동으로 저장하는 것이 가장 직관적입니다. 상태는 LocalStore, SessionStore 또는 IndexedDB에 저장할 수 있습니다. [Page A] 컴포넌트의 onMounted 후크에서 이전 상태가 존재하는지 확인하고, 존재한다면 외부 저장소에서 상태를 복원합니다. LocalStoreSessionStoreIndexedDB。在【页面A】组件的onMounted钩子中,检测是否存在此前的状态,如果存在从外部存储中将状态恢复回来。

有什么问题?

  • 浪费心智(麻烦/操心)。这个方案存在的问题就是,需要在编写组件的时候就明确的知道跳转到某些页面时进行状态存储。
  • 无法解决子组件状态。在页面组件中还可以做到保存页面组件的状态,但是如何保存子组件呢。不可能所有的子组件状态都在页面组件中维护,因为这样的结构并不是合理。

组件缓存

利用Vue的内置组件<keepalive></keepalive>缓存包裹在其中的动态切换组件(也就是<component></component>组件)。<keepalive></keepalive>包裹动态组件时,会缓存不活跃的组件,而不是销毁它们。当一个组件在<keepalive></keepalive>中被切换时,activateddeactivated生命周期钩子会替换mountedunmounted钩子。最关键的是,<keepalive></keepalive>不仅适用于被包裹组件的根节点,也适用于其子孙节点。

<keepalive></keepalive>搭配vue-router即可实现页面的保活,实现代码如下:

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

有什么问题?

  • 页面保活不准确。上面的方式虽然实现了页面保活,但是并不能满足生产要求,例如:【页面A】是应用首页,【页面B】是数据列表页,【页面C】是数据详情页。用户查看数据详情的动线是:【页面A】->【页面B】->【页面C】,在这条动线中【页面B】->【页面C】的时候需要缓存【页面B】,当从【页面C】->【页面B】的时候需要从换从中恢复【页面B】。但是【页面B】->【页面A】的时候又不需要缓存【页面B】,上面的这个方法并不能做到这样的配置。

最佳实践

最理想的保活方式是,不入侵组件代码的情况下,通过简单的配置实现按需的页面保活。

【不入侵组件代码】这条即可排除第一种方式的实现,第二种【组件缓存】的方式只是败在了【按需的页面保活】。那么改造第二种方式,通过在router的路由配置上进行按需保活的配置,再提供一种读取配置结合<keepalive></keepalive>include属性即可。

路由配置

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();
});

保活组件存储

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];
    },
  },
});

页面缓存

src/layout/index.vue

질문이 있으신가요?

  • 마음의 낭비(문제/걱정). 이 솔루션의 문제점은 특정 페이지로 이동할 때 상태를 저장하는 구성 요소를 작성할 때 명확하게 알아야 한다는 것입니다.
  • 하위 구성 요소 상태를 확인할 수 없습니다. 페이지 구성 요소의 상태를 페이지 구성 요소에 저장할 수도 있지만 하위 구성 요소를 저장하는 방법은 다음과 같습니다. 이러한 구조는 합리적이지 않기 때문에 페이지 구성 요소의 모든 하위 구성 요소 상태를 유지하는 것은 불가능합니다.

구성요소 캐시🎜Vue의 내장 구성요소 <keepalive></keepalive> 사용 code> 캐시 안에 래핑된 동적 전환 구성 요소(즉, <component></component> 구성 요소)입니다. <keepalive></keepalive>동적 구성 요소를 래핑할 때 비활성 구성 요소는 파기되는 대신 캐시됩니다. <keepalive></keepalive>에서 구성 요소가 전환되면 활성화비활성화 수명 주기 후크가 마운트된 코드를 대체합니다. > 및 마운트 해제 후크. 가장 중요한 것은 <keepalive></keepalive>가 래핑된 구성 요소의 루트 노드뿐만 아니라 해당 하위 노드에도 적용된다는 것입니다. 🎜🎜<keepalive></keepalive>vue-router와 함께 사용하여 페이지를 활성 상태로 유지할 수 있습니다. 구현 코드는 다음과 같습니다. 🎜
<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>

무엇이 문제인가요?

  • 페이지 연결 유지가 정확하지 않습니다. 위의 방법은 페이지 연결 유지를 달성하지만 제작 요구 사항을 충족할 수 없습니다. 예를 들어 [페이지 A]는 애플리케이션 홈페이지, [페이지 B]는 데이터 목록 페이지, [페이지 C]는 데이터 세부 정보 페이지입니다. 사용자가 데이터 세부정보를 볼 수 있는 이동 라인은 [페이지 A]->[페이지 B]->[페이지 C]입니다. 이 이동 라인에서는 [페이지 B]->[페이지 C]가 캐시되어야 합니다. [ 페이지 B], [페이지 C]에서 [페이지 B]로 이동하는 경우 해당 페이지에서 [페이지 B]를 복원해야 합니다. 그러나 [페이지 B] -> [페이지 A]인 경우에는 [페이지 B]를 캐시할 필요가 없습니다.

모범 사례🎜🎜🎜가장 이상적인 방법은 구성 요소 코드를 침해하지 않고 간단한 구성을 통해 온디맨드를 달성하는 것입니다. 살아있었습니다. 🎜🎜🎜[구성 요소 코드에 대한 침입 없음] 이는 첫 번째 방법의 구현을 배제합니다. 두 번째 방법 [구성 요소 캐싱]은 [주문형 페이지 연결 유지]에 의해서만 무효화됩니다. 그런 다음 라우터의 라우팅 구성에 주문형 연결 유지를 구성하여 두 번째 방법을 변환한 다음 <keepalive></keepalive>와 결합된 읽기 구성을 제공합니다. include 속성이면 충분합니다. 🎜

라우팅 구성

🎜src/router/index.ts🎜
import &#39;vue-router&#39;;

export type LeaveCaches = string[];

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

연결 유지 구성 요소 저장소

🎜src/stroe/router.ts🎜rrreee

페이지 캐시

🎜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视频教程》】

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

위 내용은 매우 편안한 Vue 페이지 유지 솔루션을 공유하세요의 상세 내용입니다. 자세한 내용은 PHP 중국어 웹사이트의 기타 관련 기사를 참조하세요!

성명:
이 기사는 juejin.im에서 복제됩니다. 침해가 있는 경우 admin@php.cn으로 문의하시기 바랍니다. 삭제