연결 유지란 무엇인가요? 다음 기사에서는 vue 내장 구성 요소 연결 유지에 대한 이해에 대해 설명하겠습니다. 도움이 되기를 바랍니다.
keep-alive
는 vue
에 내장된 구성 요소로 구성 요소 전환 중에 상태를 유지할 수 있습니다. . 메모리에서 DOM
의 반복 렌더링을 방지합니다. [관련 권장사항: vuejs 비디오 튜토리얼keep-alive
是vue
中的内置组件,能在组件切换过程中将状态保留在内存中,防止重复渲染DOM
。【相关推荐:vuejs视频教程、web前端开发】
keep-alive
包裹动态组件时,会缓存不活动的组件实例,而不是销毁它们。
keep-alive
可以设置以下props
属性:
include
- 字符串或正则表达式。只有名称匹配的组件会被缓存exclude
- 字符串或正则表达式。任何名称匹配的组件都不会被缓存max
- 数字。最多可以缓存多少组件实例关于keep-alive
的基本用法:
<keep-alive> <component :is="view"></component> </keep-alive>
使用includes
和exclude
:
<keep-alive include="a,b"> <component :is="view"></component> </keep-alive> <!-- 正则表达式 (使用 `v-bind`) --> <keep-alive :include="/a|b/"> <component :is="view"></component> </keep-alive> <!-- 数组 (使用 `v-bind`) --> <keep-alive :include="['a', 'b']"> <component :is="view"></component> </keep-alive>
匹配首先检查组件自身的 name
选项,如果 name
选项不可用,则匹配它的局部注册名称 (父组件 components
选项的键值),匿名组件不能被匹配
设置了 keep-alive 缓存的组件,会多出两个生命周期钩子(activated
与deactivated
):
beforeRouteEnter
> beforeCreate
> created
> mounted
> activated
> ... ... > beforeRouteLeave
> deactivated
beforeRouteEnter
>activated
> ... ... > beforeRouteLeave
> deactivated
使用原则:当我们在某些场景下不需要让页面重新加载时我们可以使用keepalive
举个栗子:
当我们从首页
–>列表页
–>商详页
–>再返回
,这时候列表页应该是需要keep-alive
从首页
–>列表页
–>商详页
–>返回到列表页(需要缓存)
–>返回到首页(需要缓存)
–>再次进入列表页(不需要缓存)
,这时候可以按需来控制页面的keep-alive
在路由中设置keepAlive
属性判断是否需要缓存
{ path: 'list', name: 'itemList', // 列表页 component (resolve) { require(['@/pages/item/list'], resolve) }, meta: { keepAlive: true, title: '列表页' } }
使用7c9485ff8c3cba5ae9343ed63c2dc3f7
<div id="app" class='wrapper'> <keep-alive> <!-- 需要缓存的视图组件 --> <router-view v-if="$route.meta.keepAlive"></router-view> </keep-alive> <!-- 不需要缓存的视图组件 --> <router-view v-if="!$route.meta.keepAlive"></router-view> </div>
keep-alive
是vue
中内置的一个组件
源码位置:src/core/components/keep-alive.js
export default { name: 'keep-alive', abstract: true, props: { include: [String, RegExp, Array], exclude: [String, RegExp, Array], max: [String, Number] }, created () { this.cache = Object.create(null) this.keys = [] }, destroyed () { for (const key in this.cache) { pruneCacheEntry(this.cache, key, this.keys) } }, mounted () { this.$watch('include', val => { pruneCache(this, name => matches(val, name)) }) this.$watch('exclude', val => { pruneCache(this, name => !matches(val, name)) }) }, render() { /* 获取默认插槽中的第一个组件节点 */ const slot = this.$slots.default const vnode = getFirstComponentChild(slot) /* 获取该组件节点的componentOptions */ const componentOptions = vnode && vnode.componentOptions if (componentOptions) { /* 获取该组件节点的名称,优先获取组件的name字段,如果name不存在则获取组件的tag */ const name = getComponentName(componentOptions) const { include, exclude } = this /* 如果name不在inlcude中或者存在于exlude中则表示不缓存,直接返回vnode */ if ( (include && (!name || !matches(include, name))) || // excluded (exclude && name && matches(exclude, name)) ) { return vnode } const { cache, keys } = this /* 获取组件的key值 */ const key = vnode.key == null // same constructor may get registered as different local components // so cid alone is not enough (#3269) ? componentOptions.Ctor.cid + (componentOptions.tag ? `::${componentOptions.tag}` : '') : vnode.key /* 拿到key值后去this.cache对象中去寻找是否有该值,如果有则表示该组件有缓存,即命中缓存 */ if (cache[key]) { vnode.componentInstance = cache[key].componentInstance // make current key freshest remove(keys, key) keys.push(key) } /* 如果没有命中缓存,则将其设置进缓存 */ else { cache[key] = vnode keys.push(key) // prune oldest entry /* 如果配置了max并且缓存的长度超过了this.max,则从缓存中删除第一个 */ if (this.max && keys.length > parseInt(this.max)) { pruneCacheEntry(cache, keys[0], keys, this._vnode) } } vnode.data.keepAlive = true } return vnode || (slot && slot[0]) } }
可以看到该组件没有template
,而是用了render
,在组件渲染的时候会自动执行render
函数
this.cache
是一个对象,用来存储需要缓存的组件,它将以如下形式存储:
this.cache = { 'key1':'组件1', 'key2':'组件2', // ... }
在组件销毁的时候执行pruneCacheEntry
函数
function pruneCacheEntry ( cache: VNodeCache, key: string, keys: Array<string>, current?: VNode ) { const cached = cache[key] /* 判断当前没有处于被渲染状态的组件,将其销毁*/ if (cached && (!current || cached.tag !== current.tag)) { cached.componentInstance.$destroy() } cache[key] = null remove(keys, key) }
在mounted
钩子函数中观测 include
和 exclude
的变化,如下:
mounted () { this.$watch('include', val => { pruneCache(this, name => matches(val, name)) }) this.$watch('exclude', val => { pruneCache(this, name => !matches(val, name)) }) }
如果include
或exclude
发生了变化,即表示定义需要缓存的组件的规则或者不需要缓存的组件的规则发生了变化,那么就执行pruneCache
函数,函数如下:
function pruneCache (keepAliveInstance, filter) { const { cache, keys, _vnode } = keepAliveInstance for (const key in cache) { const cachedNode = cache[key] if (cachedNode) { const name = getComponentName(cachedNode.componentOptions) if (name && !filter(name)) { pruneCacheEntry(cache, key, keys, _vnode) } } } }
在该函数内对this.cache
对象进行遍历,取出每一项的name
值,用其与新的缓存规则进行匹配,如果匹配不上,则表示在新的缓存规则下该组件已经不需要被缓存,则调用pruneCacheEntry
函数将其从this.cache
对象剔除即可
关于keep-alive
的最强大缓存功能是在render
函数中实现
首先获取组件的key
值:
const key = vnode.key == null? componentOptions.Ctor.cid + (componentOptions.tag ? `::${componentOptions.tag}` : '') : vnode.key
拿到key
值后去this.cache
, 웹 프론트엔드 개발
keep-alive
동적 구성 요소를 래핑할 때 캐시 구성 요소 인스턴스를 파괴하는 대신 비활성 구성 요소 인스턴스가 됩니다. 🎜🎜keep-alive
는 다음 props
속성을 설정할 수 있습니다: 🎜include
- 문자열 또는 정규 표현식. 이름이 일치하는 구성 요소만 캐시됩니다.제외
- 문자열 또는 정규 표현식입니다. 이름이 일치하는 구성요소는 캐시되지 않습니다.max
- 숫자. 캐시할 수 있는 최대 구성 요소 인스턴스 수keep-alive
의 기본 사용법: 🎜/* 如果命中缓存,则直接从缓存中拿 vnode 的组件实例 */ if (cache[key]) { vnode.componentInstance = cache[key].componentInstance /* 调整该组件key的顺序,将其从原来的地方删掉并重新放在最后一个 */ remove(keys, key) keys.push(key) }🎜
includes
및 exclude 사용
: 🎜/* 如果没有命中缓存,则将其设置进缓存 */ else { cache[key] = vnode keys.push(key) /* 如果配置了max并且缓存的长度超过了this.max,则从缓存中删除第一个 */ if (this.max && keys.length > parseInt(this.max)) { pruneCacheEntry(cache, keys[0], keys, this._vnode) } }🎜일치 항목은 먼저 구성 요소 자체의
name
옵션을 확인합니다. name
옵션을 사용할 수 없는 경우 로컬 등록 이름(부모)과 일치합니다. 구성 요소 구성 요소 코드> 옵션 키 값), 익명 구성 요소는 일치할 수 없습니다. 🎜🎜연결 유지 캐시가 설정된 구성 요소에는 수명 주기 후크가 두 개 더 있습니다(<code>활성화
및 비활성화됨).
): 🎜beforeRouteEnter
> beforeCreate
> > 탑재됨
> ... ... > 비활성화됨
li>beforeRouteEnter
>activated
> ... ... > code>비활성화keepalive
🎜🎜를 사용할 수 있습니다. 예:🎜🎜홈페이지
–>목록 페이지
–>비즈니스 세부정보 페이지
–>반환
이때 목록 페이지는 홈페이지
에서 연결 유지
🎜🎜해야 합니다. >–>목록 페이지
–>비즈니스 세부정보 페이지
–>목록 페이지로 돌아가기(캐싱 필요)
–> 홈페이지로 돌아가기(캐싱 필요)
– >목록 페이지 다시 입력(캐싱 필요 없음)
이때 연결 유지
를 제어할 수 있습니다. > 필요에 따라 페이지의 🎜🎜라우팅 코드에 keepAlive를 설정> 속성은 캐싱이 필요한지 여부를 결정합니다🎜<pre class="brush:js;toolbar:false;">beforeRouteEnter(to, from, next){
next(vm=>{
console.log(vm)
// 每次进入路由执行
vm.getData() // 获取数据
})
},</pre>🎜<code>7c9485ff8c3cba5ae9343ed63c2dc3f7
를 사용하세요🎜activated(){ this.getData() // 获取数据 },
keep -alive
는 vue
🎜🎜에 내장된 구성 요소입니다. 소스 코드 위치: src/core/comComponents/ keep-alive.js🎜rrreee🎜이 구성 요소에는 템플릿
이 없고 대신 렌더링
을 사용하여 자동으로 렌더링
을 실행하는 것을 볼 수 있습니다. > 컴포넌트가 렌더링될 때의 함수🎜🎜this.cache
는 캐시해야 하는 컴포넌트를 저장하는 데 사용되며 다음 형식으로 저장됩니다. 🎜rrreee🎜 를 실행합니다. 컴포넌트가 소멸될 때 pruneCacheEntry
함수 🎜rrreee🎜 mounted
후크 함수에서 관찰 includeexclude
의 변경 사항은 다음과 같습니다. : 🎜rrreee🎜 include
또는 exclude
가 변경되면 정의가 필요하다는 뜻입니다. 캐시된 구성 요소의 규칙이나 캐시할 필요가 없는 구성 요소의 규칙이 변경된 경우 , 그런 다음 pruneCache
함수를 실행합니다. 함수는 다음과 같습니다. 🎜rrreee🎜이 함수에서 this.cache
를 업데이트하고 개체를 트래버스하고 name 값을 사용하여 새 캐싱 규칙을 일치시킵니다. 일치하지 않으면 구성요소가 더 이상 새 캐싱 규칙에 따라 캐시될 필요가 없음을 의미합니다. 그런 다음 <code>pruneCacheEntry 함수를 사용하여 <code>this.cache
개체에서 제거합니다🎜🎜 keep-alive
의 가장 강력한 캐싱 기능은 렌더링
에 구현되어 있습니다. > function 🎜🎜먼저 구성 요소의 key
값을 가져옵니다. 🎜rrreee🎜 key
값을 가져온 후 this.cache 개체로 이동하여 이 값이 있는지 확인합니다. 존재하는 경우 구성 요소에 캐시가 있음을 의미합니다. 즉, 다음과 같이 캐시에 도달한다는 의미입니다.<pre class="brush:js;toolbar:false;">/* 如果命中缓存,则直接从缓存中拿 vnode 的组件实例 */
if (cache[key]) {
vnode.componentInstance = cache[key].componentInstance
/* 调整该组件key的顺序,将其从原来的地方删掉并重新放在最后一个 */
remove(keys, key)
keys.push(key)
}</pre><p>直接从缓存中拿 <code>vnode
的组件实例,此时重新调整该组件key
的顺序,将其从原来的地方删掉并重新放在this.keys
中最后一个
this.cache
对象中没有该key
值的情况,如下:
/* 如果没有命中缓存,则将其设置进缓存 */ else { cache[key] = vnode keys.push(key) /* 如果配置了max并且缓存的长度超过了this.max,则从缓存中删除第一个 */ if (this.max && keys.length > parseInt(this.max)) { pruneCacheEntry(cache, keys[0], keys, this._vnode) } }
表明该组件还没有被缓存过,则以该组件的key
为键,组件vnode
为值,将其存入this.cache
中,并且把key
存入this.keys
中
此时再判断this.keys
中缓存组件的数量是否超过了设置的最大缓存数量值this.max
,如果超过了,则把第一个缓存组件删掉
解决方案可以有以下两种:
每次组件渲染的时候,都会执行beforeRouteEnter
beforeRouteEnter(to, from, next){ next(vm=>{ console.log(vm) // 每次进入路由执行 vm.getData() // 获取数据 }) },
在keep-alive
缓存的组件被激活的时候,都会执行actived
钩子
activated(){ this.getData() // 获取数据 },
注意:服务器端渲染期间avtived
不被调用
위 내용은 Vue의 내장 구성 요소인 연결 유지에 대한 이해에 대해 이야기해 보겠습니다.의 상세 내용입니다. 자세한 내용은 PHP 중국어 웹사이트의 기타 관련 기사를 참조하세요!