美文网首页
activated、deactivated发生的生命周期具体位置

activated、deactivated发生的生命周期具体位置

作者: QLing09 | 来源:发表于2020-09-24 21:41 被阅读0次

    keep-alive 缓存的组件会多两个生命周期activateddeactivated,缓存后的组件经常会用activated这个生命周期,那么这两个生命周期和vue的其他生命周期怎么排序执行的呢?

    我们知道VUE的其他的生命周期是这样的:

    image.png

    activated 这个生命周期呢?

    我们可以从源码src/core/vdom/create-component.js看到:

    insert (vnode: MountedComponentVNode) {
        const { context, componentInstance } = vnode
        if (!componentInstance._isMounted) {
          componentInstance._isMounted = true
          callHook(componentInstance, 'mounted')
        }
        if (vnode.data.keepAlive) {
          if (context._isMounted) {
            // vue-router#1212
            // During updates, a kept-alive component's child components may
            // change, so directly walking the tree here may call activated hooks
            // on incorrect children. Instead we push them into a queue which will
            // be processed after the whole patch process ended.
            queueActivatedComponent(componentInstance)
          } else {
            activateChildComponent(componentInstance, true /* direct */)
          }
        }
      }
    
    

    从上面源码可以看到,组件的mounted挂载后,回去判断当前组件是否vnode.data.keepAlive ,如果context._isMounted是true那么有可能keep-alive组件的子组件也许会改变,因此直接在此处行走树可能会在不正确的子组件上调用已激活的钩子。相反我们把它们推入队列,整个patch过程结束后将对其进行处理。

    src/core/observer/scheduler.js

    /**
     * Queue a kept-alive component that was activated during the patch.
     * The queue will be processed after the entire tree has been patched.
     */
    export function queueActivatedComponent (vm: Component) {
      // setting _inactive to false here so that a render function can
      // rely on checking whether it's in an inactive tree (e.g. router-view)
      vm._inactive = false
      activatedChildren.push(vm)
    }
    
    ...
    ...
    /**
     * Push a watcher into the watcher queue.
     * Jobs with duplicate IDs will be skipped unless it's
     * pushed when the queue is being flushed.
     */
    export function queueWatcher (watcher: Watcher) {
      const id = watcher.id
      if (has[id] == null) {
        has[id] = true
        if (!flushing) {
          queue.push(watcher)
        } else {
          // if already flushing, splice the watcher based on its id
          // if already past its id, it will be run next immediately.
          let i = queue.length - 1
          while (i > index && queue[i].id > watcher.id) {
            i--
          }
          queue.splice(i + 1, 0, watcher)
        }
        // queue the flush
        if (!waiting) {
          waiting = true
    
          if (process.env.NODE_ENV !== 'production' && !config.async) {
            flushSchedulerQueue()
            return
          }
          nextTick(flushSchedulerQueue)
        }
      }
    }
    

    上面代码是做队列处理。

    src/core/instance/lifecycle.js

    
    export function activateChildComponent (vm: Component, direct?: boolean) {
      if (direct) {
        vm._directInactive = false
        if (isInInactiveTree(vm)) {
          return
        }
      } else if (vm._directInactive) {
        return
      }
      if (vm._inactive || vm._inactive === null) {
        vm._inactive = false
        for (let i = 0; i < vm.$children.length; i++) {
          activateChildComponent(vm.$children[i])
        }
        callHook(vm, 'activated')
      }
    }
    

    上面是发起activated

    deactivated那么是在什么时候调用的呢?

    src/core/instance/lifecycle.js

    export function deactivateChildComponent (vm: Component, direct?: boolean) {
      if (direct) {
        vm._directInactive = true
        if (isInInactiveTree(vm)) {
          return
        }
      }
      if (!vm._inactive) {
        vm._inactive = true
        for (let i = 0; i < vm.$children.length; i++) {
          deactivateChildComponent(vm.$children[i])
        }
        callHook(vm, 'deactivated')
      }
    }
    
    

    src/core/vdom/create-component.js

    destroy (vnode: MountedComponentVNode) {
        const { componentInstance } = vnode
        if (!componentInstance._isDestroyed) {
          if (!vnode.data.keepAlive) {
            componentInstance.$destroy()
          } else {
            deactivateChildComponent(componentInstance, true /* direct */)
          }
        }
      }
    

    组件是vnode.data.keepAlive的时候直接调用deactivateChildComponent,发起deactivated,不走$destroy

    以上是VUE里面keep-alive中activated、deactivated两个点发生的生命周期位置,如果有误欢迎大家在评论里面指正。

    相关文章

      网友评论

          本文标题:activated、deactivated发生的生命周期具体位置

          本文链接:https://www.haomeiwen.com/subject/gyteektx.html