>  기사  >  웹 프론트엔드  >  vue keep-alive 구성 요소의 사용 및 원리 소개

vue keep-alive 구성 요소의 사용 및 원리 소개

不言
不言앞으로
2019-03-30 09:34:532693검색

이 글의 내용은 vue keep-alive 구성요소의 사용 및 원리 소개에 관한 것입니다. 참고할 만한 가치가 있으니 도움이 필요한 분들에게 도움이 되길 바랍니다.

keep-alive

keep-alive는 vue.js에 내장된 구성 요소입니다. 비활성 구성 요소의 인스턴스를 직접 파괴하는 대신 메모리에 저장할 수 있으며 현실로 렌더링되지 않습니다. DOM의 경우 상위 구성 요소 체인에 표시되지 않습니다.
제외 및 포함이라는 두 가지 속성을 제공하여 구성 요소를 조건부로 캐시할 수 있습니다.

위의

<keep-alive>
    <comment></comment>
</keep-alive>

댓글 구성 요소를 사용하면 캐시됩니다.

<keep-alive>
    <coma v-if="test"></coma>
    <comb v-else></comb>
</keep-alive>
<button @click="abc"></button>

export default{
    data(){
        reurn{
            test:true
        }
    },
    methods:{
        abc(){
            this.test=!this.test;
        }
    }
}

버튼을 클릭하면 coma 구성요소와 Comb 구성요소가 전환되는데 이때 두 구성요소의 상태가 캐싱됩니다. 구성요소 a와 b에 입력 레이블이 있는 경우 입력 값은 다음과 같습니다. 버튼을 클릭해도 라벨은 변경되지 않습니다.

props

keep-alive 구성 요소는 조건부 캐싱을 위해 포함 및 제외라는 두 가지 속성을 제공합니다. 둘 다 쉼표로 구분된 문자열, 정규 표현식 또는 배열로 표시될 수 있습니다.

<keep-alive include="a">
    <component></component>
</keep-alive>
//name名为a的组件会被缓存起来

<keep-alive exclude="a">
    <component></component>
</keep-alive>
//name名为a的组件将不会被缓存。

Life Hook

keep-alive는 활성 및 비활성화의 두 가지 구명 후크를 제공합니다.
Keep-alive는 구성 요소를 메모리에 저장하고 파괴하거나 재구축하지 않기 때문에 구성 요소의 생성 및 기타 메서드를 호출하지 않으므로 구성 요소가 활성 상태인지 확인하려면 활성 및 비활성화 후크를 사용해야 합니다.

Keep-alive 구성 요소 구현에 대해 자세히 알아보기

생성 및 소멸 후크
생성된 후크는 Vnode 노드를 저장하기 위한 캐시 컨테이너로 사용되는 캐시 개체를 생성합니다.

created{
    this.cache=Object.create(null);
}

destroyed 후크는 구성 요소가 삭제될 때 캐시의 모든 구성 요소 인스턴스를 지웁니다.

/* destroyed钩子中销毁所有cache中的组件实例 */
destroyed () {
    for (const key in this.cache) {
        pruneCacheEntry(this.cache[key])
    }
},

다음 단계는 렌더링 기능입니다.

render () {
    /* 得到slot插槽中的第一个组件 */
    const vnode: VNode = getFirstComponentChild(this.$slots.default)

    const componentOptions: ?VNodeComponentOptions = vnode && vnode.componentOptions
    if (componentOptions) {
        // check pattern
        /* 获取组件名称,优先获取组件的name字段,否则是组件的tag */
        const name: ?string = getComponentName(componentOptions)
        /* name不在inlcude中或者在exlude中则直接返回vnode(没有取缓存) */
        if (name && (
        (this.include && !matches(this.include, name)) ||
        (this.exclude && matches(this.exclude, name))
        )) {
            return vnode
        }
        const key: ?string = 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
        /* 如果已经做过缓存了则直接从缓存中获取组件实例给vnode,还未缓存过则进行缓存 */
        if (this.cache[key]) {
            vnode.componentInstance = this.cache[key].componentInstance
        } else {
            this.cache[key] = vnode
        }
        /* keepAlive标记位 */
        vnode.data.keepAlive = true
    }
    return vnode
}

먼저 getFirstComponentChild를 통해 첫 번째 하위 컴포넌트를 가져와서 컴포넌트 이름을 가져옵니다. (컴포넌트 이름이 있으면 직접 컴포넌트 이름을 사용하고, 그렇지 않으면 태그가 사용됩니다.) 다음으로, 이름은 포함 및 제외 속성을 통해 일치됩니다. 일치에 실패하면(캐싱이 필요하지 않음을 나타냄) vnode는 어떤 작업도 없이 직접 반환됩니다.

/* 检测name是否匹配 */
function matches (pattern: string | RegExp, name: string): boolean {
  if (typeof pattern === 'string') {
    /* 字符串情况,如a,b,c */
    return pattern.split(',').indexOf(name) > -1
  } else if (isRegExp(pattern)) {
    /* 正则 */
    return pattern.test(name)
  }
  /* istanbul ignore next */
  return false
}

포함 및 제외 속성의 일치를 감지하는 기능은 매우 간단합니다. 포함 및 제외 속성은 구성 요소 이름이 쉼표와 정규식으로 구분되는 "a,b,c"와 같은 문자열을 지원합니다. match는 이 두 가지 방법을 사용하여 현재 구성 요소와 일치하는지 여부를 검색합니다.

if (this.cache[key]) {
    vnode.componentInstance = this.cache[key].componentInstance
} else {
    this.cache[key] = vnode
}

다음은 매우 간단합니다. 키에 따라 this.cache에서 찾으면 이전에 캐시된 vnode를 현재 vnode에 직접 덮어쓴다는 의미입니다. 그렇지 않으면 vnode가 캐시에 저장됩니다.
마지막으로 vnode로 돌아갑니다(캐시가 있는 경우 vnode의 구성 요소 인스턴스가 캐시에 있는 구성 요소 인스턴스로 대체되었습니다).
watch를 사용하여 pruneCache 및 pruneCache 속성의 변경 사항을 모니터링하고 변경 시 캐시 캐시의 캐시 데이터를 수정합니다.

watch: {
    /* 监视include以及exclude,在被修改的时候对cache进行修正 */
    include (val: string | RegExp) {
        pruneCache(this.cache, this._vnode, name => matches(val, name))
    },
    exclude (val: string | RegExp) {
        pruneCache(this.cache, this._vnode, name => !matches(val, name))
    }
},

pruneCache 구현을 살펴보겠습니다.

/* 修正cache */
function pruneCache (cache: VNodeCache, current: VNode, filter: Function) {
  for (const key in cache) {
    /* 取出cache中的vnode */
    const cachedNode: ?VNode = cache[key]
    if (cachedNode) {
      const name: ?string = getComponentName(cachedNode.componentOptions)
      /* name不符合filter条件的,同时不是目前渲染的vnode时,销毁vnode对应的组件实例(Vue实例),并从cache中移除 */
      if (name && !filter(name)) {
        if (cachedNode !== current) {
          pruneCacheEntry(cachedNode)
        }
        cache[key] = null
      }
    }
  }
} 

/* 销毁vnode对应的组件实例(Vue实例) */
function pruneCacheEntry (vnode: ?VNode) {
  if (vnode) {
    vnode.componentInstance.$destroy()
  }
}

캐시의 모든 항목을 탐색하여 필터에 지정된 규칙을 충족하지 않으면 pruneCacheEntry가 실행됩니다. pruneCacheEntry는 구성 요소 인스턴스의 $destroy 메서드를 호출하여 구성 요소를 삭제합니다.

이 기사는 여기까지입니다. 더 많은 흥미로운 콘텐츠를 보려면 PHP 중국어 웹사이트의 JavaScript Video Tutorial 칼럼을 주목하세요!

위 내용은 vue keep-alive 구성 요소의 사용 및 원리 소개의 상세 내용입니다. 자세한 내용은 PHP 중국어 웹사이트의 기타 관련 기사를 참조하세요!

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