keepalive는 vue3의 전역 구성 요소입니다
keepalive 자체는 렌더링되지 않으며 dom 노드에도 표시되지 않지만 vnode로 렌더링되며 이를 통해 추적할 수 있습니다. vnode Keepalive의 캐시와 키는 물론 개발 환경에서만 사용할 수 있습니다. 빌드 패키지 후에는 vnode에 노출되지 않습니다(이것은 다시 확인해야 합니다)
keepalive 가장 중요한 기능은 캐시 구성 요소입니다.
keepalive through LRU 캐시 제거 전략은 구성 요소 캐시를 업데이트하는 데 사용되며, 이를 통해 메모리를 보다 효율적으로 사용하고 메모리 오버플로를 방지할 수 있습니다. 소스 코드의 최대 캐시 수는 10개입니다. 즉, 구성 요소 10개 이후입니다.
가정해 보겠습니다. A 페이지는 홈 페이지입니다. =====> 캐시됨) =======> C 세부정보 페이지 by C 세부정보 페이지가 B 페이지에 도달하면 페이지의 기본 데이터와 페이지의 스크롤바 위치 정보를 포함하여 B 캐시 페이지로 돌아가야 합니다. 목록 B 페이지에서 A 페이지로 돌아가면 B 캐시 페이지를 지워야 합니다
위에서 언급한 또 다른 시나리오: 페이지에 들어가서 직접 캐시하면 이 작업은 비교적 간단하고 끝납니다.
keepalive 구성요소에는 총 3개의 매개변수가 있습니다
include: 문자열, 정규식 및 배열이 전달될 수 있습니다. 성공적으로 일치하는 이름이 있는 구성 요소는 캐시됩니다.
exclude: 문자열, 정규 표현식 및 배열이 전달될 수 있습니다. 성공적으로 일치하는 이름이 있는 구성 요소는 캐시되지 않습니다.
max: 최대 수를 제한하는 통과 가능한 숫자입니다. 캐시된 구성 요소의 기본값은 10
먼저 App.vue 루트 코드에 keepalive 구성 요소를 추가하고 도입하면 여기에 캐시된 내용이 전체 페이지와 동일하다는 것을 알 수 있습니다. 또한 페이지 내 특정 영역 컴포넌트를 좀 더 세밀하게 제어할 수 있습니다
<template> <router-view v-slot="{ Component }"> <keep-alive :include="keepAliveCache"> <component :is="Component" :key="$route.name" /> </keep-alive> </router-view> </template> <script lang="ts" setup> import { computed } from "vue"; import { useKeepAliverStore } from "@/store"; const useStore = useKeepAliverStore(); const keepAliveCache = computed(() => { return useStore.caches; }); </script>
App.vue를 통해 찾을 수 있고, pinia(즉, vue2에서 사용하는 vuex)를 통해 캐시할 페이지 컴포넌트를 저장하여 include를 처리할 수 있습니다. 캐싱하고 페이지 컴포넌트에 스크롤 막대 정보 데이터를 저장합니다
import { defineStore } from "pinia"; export const useKeepAliverStore = defineStore("useKeepAliverStore", { state: () => ({ caches: [] as any, scrollList: new Map(), // 缓存页面组件如果又滚动条的高度 }), actions: { add(name: string) { this.caches.push(name); }, remove(name: string) { console.log(this.caches, 'this.caches') this.caches = this.caches.filter((item: any) => item !== name); console.log(this.caches, 'this.caches') }, clear() { this.caches = [] } } });
컴포넌트 경로가 방금 전환되면 beforeRouteEnter를 통해 해당 컴포넌트를 include에 씁니다. 이때는 컴포넌트 수명 주기가 아직 시작되지 않았습니다. 컴포넌트 라이프사이클의 실행이 이미 시작된 경우 다시 작성하는 것이 좋습니다.
따라서 이 후크 기능은 설정에서 작성할 수 없고 별도로 작성해야 합니다. 물론 beforeEach를 처리하기 위해 라우팅의 다른 Hook 기능으로 전환할 수도 있지만 여기서 사용할 경우 pinia를 사용할 수 없는 것으로 보입니다.
import { useRoute, useRouter, onBeforeRouteLeave } from "vue-router"; import { useKeepAliverStore } from "@/store"; const useStore = useKeepAliverStore() export default { name:"record-month", beforeRouteEnter(to, from, next) { next(vm => { if(from.name === 'Home' && to.name === 'record-month') { useStore.add(to.name) } }); } } </script>
컴포넌트 경로가 떠날 때 캐시 밖으로 이동할지 여부를 판단합니다. 이 후크는 설정에서 직접 작성할 수 있습니다.
onBeforeRouteLeave((to, from) => { console.log(to.name, "onBeforeRouteLeave"); if (to.name === "new-detection-detail") { console.log(to, from, "进入详情页面不做处理"); } else { useStore.remove(from.name) console.log(to, from, "删除组件缓存"); } });
keepalive의 두 가지 후크 기능에 스크롤 위치를 캐시하고, onActivated에서 캐시의 위치를 가져오고, onDeactivated에서 캐시의 위치를 기록합니다.
onActivated(() => { if(useStore.scrollList.get(routeName)) { const top = useStore.scrollList.get(routeName) refList.value.setScrollTop(Number(top)) } }); onDeactivated(() => { const top = refList.value.getScrollTop() useStore.scrollList.set(routeName, top) });
네이티브 자바스크립트 API를 사용하여 scrollTop을 설정하는 메소드가 여기에 정의되어 있습니다
const setScrollTop = (value: any) => { const dom = document.querySelector('.van-pull-refresh') dom!.scrollTop = value }
동시에 높이를 구하는 방법은? 먼저 스크롤 이벤트를 등록한 다음 getScrollTop을 통해 현재 스크롤 막대 위치를 가져와서 저장해야 합니다.
onMounted(() => { scrollDom.value = document.querySelector('.van-pull-refresh') as HTMLElement const throttledFun = useThrottleFn(() => { console.log(scrollDom.value?.scrollTop, 'addEventListener') state.scrollTop = scrollDom.value!.scrollTop }, 500) if(scrollDom.value) { scrollDom.value.addEventListener('scroll',throttledFun) } }) const getScrollTop = () => { console.log('scrollDom.vaue', scrollDom.value?.scrollTop) return state.scrollTop }
useThrottleFn은 위의 스크롤 이벤트를 등록하는 데 사용됩니다. 많은 도구들이 매우 훌륭하다는 것을 캡슐화한 @vueuse/core에 제공됩니다. 관심이 있으시면 공부해 보세요
https://vueuse.org/shared/usethrottlefn/#usethrottlefn
이때 발견된 인스턴스의 vnode를 확인하여 에 있는 keepalive를 찾을 수도 있습니다. keepalive
const instance = getCurrentInstance() console.log(instance.vnode.parent) // 这里便是keepalive组件vnode // 如果是在开发环境中可以查看到cache对象 instance.vnode.parent.__v_cache // vue源码中,在dev环境对cache进行暴露,生产环境是看不到的 if (__DEV__ || __FEATURE_PROD_DEVTOOLS__) { ;(instance as any).__v_cache = cache }
1, 코드를 복제합니다
git clone git@github.com:vuejs/core.git
2. pnpm을 사용할 수 없는 경우 먼저 npm을 통해 설치할 수 있습니다
pnpm i.
4. 설치가 완료되면 루트 디렉토리의 package.json 파일에서 스크립트를 찾으세요
npm i pnpm -g
참고 https://www.yisu.com/article/154583.htm
5 pnpm run dev를 실행하세요. vue 소스 코드가 빌드됩니다
// 在dev命令后添加 --source-map是从已转换的代码,映射到原始的源文件 "dev": "node scripts/dev.js --sourcemap"
6....corepackagesvueexamplescomposition에 aehyok.html 파일을 추가하고 다음 코드를 추가합니다. 복사한 후 크롬 브라우저 F12를 통해 열고 소스의 탭 페이지를 찾습니다. 코드에서 단축키 Ctrl+P를 사용하여 KeepAlive를 입력하여 이 구성 요소를 찾은 다음 왼쪽의 선 표시를 마우스 오른쪽 버튼으로 클릭하여 디버깅을 위한 중단점을 추가하거나 오른쪽의 [Call Stack]을 사용하여 빠르게 이동합니다. 디버깅을 위한 코드입니다.
pnpm run dev //则会出现以下,代表成功了(2022年5月27日),后期vue源代码作者可能会更新,相应的提示可能发生变更,请注意一下 > @3.2.36 dev H:\github\sourceCode\core > node scripts/dev.js --sourcemap watching: packages\vue\dist\vue.global.js //到..\..\core\packages\vue\dist便可以看到编译成功,以及可以查看到examples样例demo页面
7 소스 코드를 디버깅하면 하위 구성 요소가 전환될 때 keepalive의 렌더링 기능(또는 설정의 반환 기능)이 실행되어 로직 캐시가 변경되는 것으로 나타났습니다
5. vue3 keealive 소스 코드 간략 분석
<script src="../../dist/vue.global.js"></script> <script type="text/x-template" id="template-1"> <div>template-1</div> <div>template-1</div> </script> <script type="text/x-template" id="template-2"> <div>template-2</div> <div>template-2</div> </script> <script> const { reactive, computed } = Vue const Demo1 = { name: 'Demo1', template: '#template-1', setup(props) { } } const Demo2 = { name: 'Demo2', template: '#template-2', setup(props) { } } </script> <!-- App template (in DOM) --> <div id="demo"> <div>Hello World</div> <div>Hello World</div> <div>Hello World</div> <button @click="changeClick(1)">组件一</button> <button @click="changeClick(2)">组件二</button> <keep-alive :include="includeCache"> <component :is="componentCache" :key="componentName" v-if="componentName" /> </keep-alive> </div> <!-- App script --> <script> Vue.createApp({ components: { Demo1, Demo2 }, data: () => ({ includeCache: [], componentCache: '', componentName: '', }), methods:{ changeClick(type) { if(type === 1) { if(!this.includeCache.includes('Demo1')) { this.includeCache.push('Demo1') } console.log(this.includeCache, '000') this.componentCache = Demo1 this.componentName = 'Demo1' } if(type === 2) { if(!this.includeCache.includes('Demo2')) { this.includeCache.push('Demo2') } console.log(this.includeCache, '2222') this.componentName = 'Demo2' this.componentCache = Demo2 } } } }).mount('#demo') </script>
위 내용은 vue3 keepalive 온라인 문제를 해결하는 방법의 상세 내용입니다. 자세한 내용은 PHP 중국어 웹사이트의 기타 관련 기사를 참조하세요!