Home  >  Article  >  Web Front-end  >  Introduction to the use and principles of vue keep-alive components

Introduction to the use and principles of vue keep-alive components

不言
不言forward
2019-03-30 09:34:532687browse

The content of this article is about the use and principle introduction of vue keep-alive components. It has certain reference value. Friends in need can refer to it. I hope it will be helpful to you.

keep-alive

keep-alive is a built-in component of vue.js. It can save instances of inactive components in memory instead of destroying them directly. It is an abstraction Components will not be rendered into the real DOM, nor will they appear in the parent component chain.
It provides two attributes, exclude and include, allowing components to be cached conditionally.

Using

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

The comment component above will be cached.

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

When the button is clicked, the coma component and the comb component will switch, but the status of the two components will be cached at this time. If there is an input label in the a and b components, then the input will be switched. The value of the label will not change.

props

keep-alive component provides two attributes, include and exclude, for conditional caching. Both of them can be represented by comma-separated strings, regular expressions, or arrays.

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

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

Life hook

keep-alive provides two life hooks, actived and deactived.
Because keep-alive will save the component to the memory and will not destroy or rebuild it, it will not call the component's creted and other methods. You need to use actived and deactived hooks to determine whether the component is active.

In-depth implementation of the keep-alive component

created and destroyed hooks
The created hook will create a cache object, which is used as a cache container to save Vnode nodes.

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

The destroyed hook clears all component instances in the cache when the component is destroyed.

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

The next step is the render function.

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
}

First get the first subcomponent through getFirstComponentChild and get the name of the component (if the component name exists, use the component name directly, otherwise the tag will be used). Next, the name will be matched through the include and exclude attributes. If the match is unsuccessful (indicating that caching is not required), the vnode will be returned directly without any operation.

/* 检测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
}

The function to detect the matching of include and exclude attributes is very simple. The include and exclude attributes support strings such as "a,b,c" where component names are separated by commas and regular expressions. matches uses these two methods to detect whether it matches the current component.

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

The next thing is very simple. Search this.cache according to the key. If it exists, it means it has been cached before. Directly overwrite the componentInstance (component instance) of the cached vnode to the current vnode. . Otherwise the vnode is stored in the cache.
Finally return to the vnode (when there is a cache, the componentInstance of the vnode has been replaced with the one in the cache).
Use watch to monitor changes in the pruneCache and pruneCache properties, and modify the cache data in the cache cache when they change.

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

Let’s take a look at the implementation of 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()
  }
}

Traverse all items in the cache. If they do not meet the rules specified by filter, pruneCacheEntry will be executed. pruneCacheEntry will call the $destroy method of the component instance to destroy the component.

This article has ended here. For more other exciting content, you can pay attention to the JavaScript Video Tutorial column on the PHP Chinese website!

The above is the detailed content of Introduction to the use and principles of vue keep-alive components. For more information, please follow other related articles on the PHP Chinese website!

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