Heim > Web-Frontend > js-Tutorial > Hauptteil

Vues Lebenszyklus und Quellcode-Implementierung (Code)

不言
Freigeben: 2018-09-07 16:57:48
Original
2239 Leute haben es durchsucht

Der Inhalt dieses Artikels befasst sich mit dem Lebenszyklus und der Quellcode-Implementierung (Code) von Vue. Ich hoffe, dass er für Freunde hilfreich ist.

Durch das Lernen haben wir die gesamte grundlegende Syntax von Vue gelernt, einschließlich:

1, {{Mustache}}-Syntax
2. v-if, v-else, v-else-if, v-show
3. v-für
4. v-bind
5. V-Modell
6. v-on

Wenn Sie diese Grammatiken bereits im Kopf haben, lesen Sie bitte weiter. Wenn Sie diese Grammatiken nicht sehr gut beherrschen, werden Sie sich hoffentlich die vorherigen ansehen.

In diesem Kapitel untersuchen wir Vues Lebenszyklus. Werfen wir zunächst einen Blick auf die Definition von Vues Lebenszyklus.

Jede Vue-Instanz durchläuft beim Erstellen eine Reihe von Initialisierungsprozessen. Sie müssen beispielsweise die Datenüberwachung einrichten, Vorlagen kompilieren, die Instanz im DOM bereitstellen und das DOM aktualisieren, wenn sich die Daten ändern , usw. Gleichzeitig werden während dieses Prozesses auch einige Funktionen namens Lebenszyklus-Hooks ausgeführt, die Benutzern die Möglichkeit geben, in verschiedenen Phasen ihren eigenen Code hinzuzufügen.

Dies sind die Beschreibungsinformationen, die auf der offiziellen Website von Vue bereitgestellt werden: Während des Prozesses von Vue von der Erstellung einer Instanz bis zur endgültigen Zerstörung wird eine Reihe entsprechender Methoden ausgeführt Nach dem aktuellen Vue-Status nennen wir diese Methoden: Lebenszyklus-Hooks . Schauen wir uns das Lebenszyklusdiagramm unten an:

Vues Lebenszyklus und Quellcode-Implementierung (Code)

Im obigen Diagramm werden insgesamt 8 Lebenszyklus-Hook-Funktionen angezeigt Diese Funktion beschreibt den gesamten Laufzyklus von Vue. Derzeit ist die Vue-Version -2.5.16. Vue verfügt über insgesamt 11 Lebenszyklus-Hooks. Zusätzlich zu den bisherigen 8 gibt es auch 3 Lebenszyklus-Hooks für die -Komponente . Werfen wir einen Blick auf alle Hook-Funktionserklärungen und anhand des obigen Diagramms können wir den Vue-Laufzyklus besser verstehen.

1. beforeCreate: Wird nach der Instanzinitialisierung und vor der Konfiguration des Datenbeobachters und des Ereignisses/Beobachterereignisses aufgerufen.
2. erstellt: Wird unmittelbar nach der Erstellung der Instanz aufgerufen. In diesem Schritt hat die Instanz die folgende Konfiguration abgeschlossen: Datenbeobachter, Vorgänge für Eigenschaften und Methoden sowie Rückrufe von Überwachungs-/Ereignisereignissen. Allerdings hat die Montagephase noch nicht begonnen und das Attribut $el ist derzeit nicht sichtbar.
3. beforeMount: Wird vor dem Mounten aufgerufen: Die zugehörige Renderfunktion wird zum ersten Mal aufgerufen.
4. mounted: el wird durch das neu erstellte vm.$el ersetzt und der Hook wird aufgerufen, nachdem er in der Instanz gemountet wurde. Wenn die Root-Instanz ein Element im Dokument mountet, befindet sich vm.$el auch im Dokument, wenn „mounting“ aufgerufen wird (PS: Beachten Sie, dass „mounted“ nicht verspricht, dass alle untergeordneten Komponenten auch zusammen gemountet werden. Wenn Sie warten möchten, bis die gesamte Ansicht ist fertig gerendert, Sie können mounted durch vm.$nextTick ersetzen :). vm.$nextTickEs wird in den folgenden Kapiteln ausführlich erklärt. Jeder muss diese Sache hier wissen.
5. beforeUpdate: Wird aufgerufen, wenn die Daten aktualisiert werden, was vor dem Patchen des virtuellen DOM geschieht. Dies eignet sich für den Zugriff auf das vorhandene DOM vor der Aktualisierung, beispielsweise zum manuellen Entfernen eines hinzugefügten Ereignis-Listeners.
6. aktualisiert: Dieser Hook wird aufgerufen, nachdem das virtuelle DOM aufgrund von Datenänderungen neu gerendert und gepatcht wurde. Wenn dieser Hook aufgerufen wird, wurde das Komponenten-DOM aktualisiert, sodass Sie jetzt Vorgänge ausführen können, die vom DOM abhängen. In den meisten Fällen sollten Sie jedoch einen Zustandswechsel in diesem Zeitraum vermeiden. Wenn Sie auf Zustandsänderungen reagieren möchten, ist es normalerweise am besten, stattdessen berechnete Eigenschaften oder Watcher zu verwenden (PS: Berechnete Eigenschaften und Watcher werden in späteren Kapiteln vorgestellt).
7. aktiviert: Wird aufgerufen, wenn die Keep-Alive-Komponente aktiviert ist (PS: Bezogen auf die Komponente wird Ihnen Keep-Alive bei der Erläuterung der Komponente vorgestellt).
8. deaktiviert: Wird aufgerufen, wenn die Keep-Alive-Komponente deaktiviert ist (PS: Bezogen auf die Komponente wird Ihnen Keep-Alive bei der Erläuterung der Komponente vorgestellt).
9. beforeDestroy: Wird aufgerufen, bevor die Instanz zerstört wird. Zu diesem Zeitpunkt ist die Instanz noch vollständig verfügbar.
10. zerstört: Wird aufgerufen, nachdem die Vue-Instanz zerstört wurde. Beim Aufruf wird alles, auf das die Vue-Instanz verweist, entbunden, alle Ereignis-Listener werden entfernt und alle untergeordneten Instanzen werden zerstört.
11. errorCaptured (neu in 2.5.0+): Wird aufgerufen, wenn ein Fehler von einer Nachkommenkomponente erfasst wird. Dieser Hook empfängt drei Parameter: das Fehlerobjekt, die Komponenteninstanz, in der der Fehler aufgetreten ist, und eine Zeichenfolge mit Informationen über die Fehlerquelle. Dieser Hook kann false zurückgeben, um zu verhindern, dass sich der Fehler weiter nach oben ausbreitet.

Dies sind alle Lebenszyklus-Hooks in Vue (2.5.16), um es für alle verständlicher zu machen, werfen wir einen Blick auf aus bis Zerstörung umgesetzt wird. Sie können hier klicken, um den neuesten Code von Vue herunterzuladen.

Werfen wir zunächst einen kurzen Blick daraufVue源代码的基础结构.

.
├── BACKERS.md ├── LICENSE
├── README.md├── benchmarks
├── dist
├── examples
├── flow
├── node_modules
├── package.json├── packages
├── scripts
├── src
├── test
├── types
└── yarn.lock
Nach dem Login kopieren

Dies ist das Verzeichnis der ersten Ebene nach dem Herunterladen des Codes, dist文件夹下为Vue编译之后的代码,我们平时引入的Vue.js文件都在这里, Vue使用了flow作为JavaScript静态类型检查工具,相关的代码都在flow文件夹下面, scripts文件夹下面是代码构建的相关配置,Vue主要使用Rollup进行的代码构建, src文件夹下面就是所有Vue的源代码. Wir werden hier nicht zu viele andere Inhalte beschreiben, sondern uns auf unser Thema konzentrieren: Wie der Lebenszykluscode von Vue implementiert wird, werfen wir einen Blick auf den Ordner src.

.
├── compiler :Vue编译相关
├── core    :Vue的核心代码
├── platforms   :web/weex平台支持,入口文件
├── server  :服务端
├── sfc :解析.vue文件
└── shared  :公共代码
Nach dem Login kopieren

Dies ist die Verzeichnisstruktur unter unserem Ordner src, und der Ort, an dem unser Vue generiert wird, befindet sich in /src/core/instance/index.js.

function Vue (options) {
  if (process.env.NODE_ENV !== 'production' &&
    !(this instanceof Vue)
  ) {
    warn('Vue is a constructor and should be called with the `new` keyword')
  }  this._init(options)
}
Nach dem Login kopieren

Wir können sehen: Vue ist eine Methode, ein Konstruktor, der mit Function implementiert wird, sodass wir Instanzen von Vue nur über new erstellen können. Initialisieren Sie dann Vue mit der Vue实例-Methode von _init. _init ist ein prototype, das von Vue bis 原型属性 implementiert wird. Werfen wir einen Blick auf seine _init Methodenimplementierung.

Unter dem Ordner /src/core/instance/init.js implementiert Vue die _init-Methode

Vue.prototype._init = function (options?: Object) {    ...
    // expose real self
    vm._self = vm
    initLifecycle(vm)
    initEvents(vm)
    initRender(vm)
    callHook(vm, 'beforeCreate')
    initInjections(vm) // resolve injections before data/props
    initState(vm)
    initProvide(vm) // resolve provide after data/props
    callHook(vm, 'created')    ...
    if (vm.$options.el) {
      vm.$mount(vm.$options.el)
    }
 }
Nach dem Login kopieren

Ich schaue mir hauptsächlich den Code an, der sich auf seinen Lebenszyklus bezieht. Wir können sehen, dass Vue先调用了initLifecycle(vm)、initEvents(vm)、initRender(vm) diese drei Methoden verwendet werden um 生命周期、事件、渲染函数 zu initialisieren. Diese Prozesse finden innerhalb von Vue初始化的过程(_init方法)中 und vor dem Aufruf von beforeCreate钩子 statt.

Dann ruft Vue callHook (vm: Component, hook: string) über die Methode 钩子函数(hook) auf, die vm(Vue实例对象),hook(钩子函数名称) empfängt, um 生命周期函数 auszuführen. In Vue werden fast alle Hook-Funktionen (außer ) in Vue über errorCaptured aufgerufen. Schauen wir uns den Code von callHook (vm: Component, hook: string) unter an: callHook

export function callHook (vm: Component, hook: string) {
  // #7573 disable dep collection when invoking lifecycle hooks
  pushTarget()  const handlers = vm.$options[hook]  
  if (handlers) {    
  for (let i = 0, j = handlers.length; i < j; i++) {      
  try {
        handlers[i].call(vm)
      } catch (e) {
        handleError(e, vm, `${hook} hook`)
      }
    }
  }  if (vm._hasHookEvent) {
    vm.$emit(&#39;hook:&#39; + hook)
  }
  popTarget()
}
Nach dem Login kopieren
/src/core/instance/lifecycle.js Seine Logik ist ebenfalls sehr einfach. Entsprechend dem eingehenden

wird das entsprechende Callback-Funktionsarray von der Instanz abgerufen (. unter <

unter 🎜>) und führen Sie es dann bequem aus. hook/packages/vue-template-compiler/browser.js ruft dann LIFECYCLE_HOOKS nach der Initialisierung

auf. Zu diesem Zeitpunkt:

Wir haben keine Möglichkeit, 生命周期、事件、渲染函数 und andere Daten beforeCreate钩子 abzurufen. data、propsNach dem Aufruf von werden diese drei Methoden zum Initialisieren von

usw. verwendet. Nachdem diese Initialisierungen abgeschlossen sind, wird

aufgerufen beforeCreate钩子 und andere Daten bereits erhalten, aber Vue ist noch nicht gestartet Vue调用了initInjections(vm)、initState(vm)、initProvide(vm), daher können wir noch nicht auf das DOM zugreifen (PS: Wir können über data、props、watcher darauf zugreifen, was wir in den folgenden Kapiteln ausführlich erläutern werden ). created钩子函数data、propsNach dem Aufruf von 渲染DOM beginnt vm.$nextTickVue mit dem Mounten des DOM und führt

aus. Das Mounten von DOM in Vue erfolgt durch den Prototyp von

Methoden kommen und gehen. created钩子Die Deklaration der Prototypmethode befindet sich in . Schauen wir uns die Implementierung dieses Codes an:

const mount = Vue.prototype.$mount
Vue.prototype.$mount = function (
  el?: string | Element,
  hydrating?: boolean
): Component {
  el = el && query(el)  
  /* istanbul ignore if */
  if (el === document.body || el === document.documentElement) {
    process.env.NODE_ENV !== &#39;production&#39; && warn(
      `Do not mount Vue to <html> or <body> - mount to normal elements instead.`
    )    return this
  }  const options = this.$options  
  // resolve template/el and convert to render function
  if (!options.render) {
    let template = options.template    
    if (template) {      
    if (typeof template === &#39;string&#39;) {        
    if (template.charAt(0) === &#39;#&#39;) {
          template = idToTemplate(template)          
          /* istanbul ignore if */
          if (process.env.NODE_ENV !== &#39;production&#39; && !template) {
            warn(
              `Template element not found or is empty: ${options.template}`,              this
            )
          }
        }
      } else if (template.nodeType) {
        template = template.innerHTML
      } else {        if (process.env.NODE_ENV !== &#39;production&#39;) {
          warn(&#39;invalid template option:&#39; + template, this)
        }        return this
      }
    } else if (el) {
      template = getOuterHTML(el)
    }    if (template) {      
    /* istanbul ignore if */
      if (process.env.NODE_ENV !== &#39;production&#39; && config.performance && mark) {
        mark(&#39;compile&#39;)
      }      
      const { render, staticRenderFns } = compileToFunctions(template, {
        shouldDecodeNewlines,
        shouldDecodeNewlinesForHref,
        delimiters: options.delimiters,
        comments: options.comments
      }, this)
      options.render = render
      options.staticRenderFns = staticRenderFns      
      /* istanbul ignore if */
      if (process.env.NODE_ENV !== &#39;production&#39; && config.performance && mark) {
        mark(&#39;compile end&#39;)
        measure(`vue ${this._name} compile`, &#39;compile&#39;, &#39;compile end&#39;)
      }
    }
  }  return mount.call(this, el, hydrating)
}
/**
 * Get outerHTML of elements, taking care
 * of SVG elements in IE as well.
 */function getOuterHTML (el: Element): string {
  if (el.outerHTML) {    
  return el.outerHTML
  } else {    
  const container = document.createElement(&#39;p&#39;)
    container.appendChild(el.cloneNode(true))    
    return container.innerHTML
  }
}
Nach dem Login kopieren
vm.$mount(vm.$options.el)Die Hauptfunktion dieses Teils des Codes: Vue.prototype.$mount besteht darin, Vue.prototype.$mount/src/platforms/web/entry-runtime-with-compiler.js. Wie aus dem obigen Code ersichtlich ist, darf

el nicht auf Root-Tags wie

und gemountet werden. template模板的解析 Bestimmen Sie dann, ob vorhanden ist, und bestimmen Sie dann, ob vorhanden ist. Die Vorlage kann bodyhtml, render函数 -> if (!options.render) {...} sein. Wenn nicht, analysieren Sie template als . Aus dem obigen Code ist ersichtlich, dass string类型的id unabhängig davon, ob wir DOM节点 verwenden oder übergeben, schließlich die gesamte Vorlage el in Form der Funktion template analysiert. 单文件组件(.Vue) Aus unserem Diagramm können wir ersehen, dass nach Abschluss der Vorlagenanalyse el、template属性 aufgerufen wird. Wo heißt dieses render? Schauen wir nach unten. Die Prototyp-Methode hat ein wiederverwendbares Design. Unter

gibt es einen solchen Code

// public mount method
Vue.prototype.$mount = function (
  el?: string | Element,
  hydrating?: boolean
): Component {
  el = el && inBrowser ? query(el) : undefined
  return mountComponent(this, el, hydrating)
}
Nach dem Login kopieren

这是一个公共的挂载方法,目的是为了被runtime only版本的Vue直接使用,它调用了mountComponent方法。我们看一下mountComponent方法的实现,实现在/src/core/instance/lifecycle.js下。

export function mountComponent (
  vm: Component,
  el: ?Element,
  hydrating?: boolean
): Component {
  vm.$el = el  
  if (!vm.$options.render) {
    vm.$options.render = createEmptyVNode    
    if (process.env.NODE_ENV !== &#39;production&#39;) {      
    /* istanbul ignore if */
      if ((vm.$options.template && vm.$options.template.charAt(0) !== &#39;#&#39;) ||
        vm.$options.el || el) {
        warn(          
        &#39;You are using the runtime-only build of Vue where the template &#39; +          
        &#39;compiler is not available. Either pre-compile the templates into &#39; +          
        &#39;render functions, or use the compiler-included build.&#39;,
          vm
        )
      } else {
        warn(          
        &#39;Failed to mount component: template or render function not defined.&#39;,
          vm
        )
      }
    }
  }
  callHook(vm, &#39;beforeMount&#39;)

  let updateComponent  
  /* istanbul ignore if */
  if (process.env.NODE_ENV !== &#39;production&#39; && config.performance && mark) {
    updateComponent = () => {      
    const name = vm._name      
    const id = vm._uid      
    const startTag = `vue-perf-start:${id}`      
    const endTag = `vue-perf-end:${id}`

      mark(startTag)      
      const vnode = vm._render()
      mark(endTag)
      measure(`vue ${name} render`, startTag, endTag)

      mark(startTag)
      vm._update(vnode, hydrating)
      mark(endTag)
      measure(`vue ${name} patch`, startTag, endTag)
    }
  } else {
    updateComponent = () => {
      vm._update(vm._render(), hydrating)
    }
  }  
  // we set this to vm._watcher inside the watcher&#39;s constructor
  // since the watcher&#39;s initial patch may call $forceUpdate (e.g. inside child
  // component&#39;s mounted hook), which relies on vm._watcher being already defined
  new Watcher(vm, updateComponent, noop, null, true /* isRenderWatcher */)
  hydrating = false

  // manually mounted instance, call mounted on self
  // mounted is called for render-created child components in its inserted hook
  if (vm.$vnode == null) {
    vm._isMounted = true
    callHook(vm, &#39;mounted&#39;)
  }  
  return vm
}
Nach dem Login kopieren

由上面的代码可以看出在执行vm._render()之前,调用了callHook(vm, &#39;beforeMount&#39;),这个时候相关的 render 函数首次被调用,调用完成之后,执行了callHook(vm, &#39;mounted&#39;)方法,标记着el 被新创建的 vm.$el 替换,并被挂载到实例上。

然后就进入了我们页面正常交互的时间,也就是beforeUpdateupdated这两个回调钩子的执行时机。这两个钩子函数是在数据更新的时候进行回调的函数,Vue在/src/core/instance/lifecycle.js文件下有一个_update的原型声明:

Vue.prototype._update = function (vnode: VNode, hydrating?: boolean) {
    const vm: Component = this    
    if (vm._isMounted) {
      callHook(vm, &#39;beforeUpdate&#39;)
    }    const prevEl = vm.$el
    const prevVnode = vm._vnode    
    const prevActiveInstance = activeInstance
    activeInstance = vm
    vm._vnode = vnode    
    // Vue.prototype.__patch__ is injected in entry points
    // based on the rendering backend used.
    if (!prevVnode) {      
    // initial render
      vm.$el = vm.__patch__(
        vm.$el, vnode, hydrating, false 
        /* removeOnly */,
        vm.$options._parentElm,
        vm.$options._refElm
      )      
      // no need for the ref nodes after initial patch
      // this prevents keeping a detached DOM tree in memory (#5851)
      vm.$options._parentElm = vm.$options._refElm = null
    } else {      
    // updates
      vm.$el = vm.__patch__(prevVnode, vnode)
    }
    activeInstance = prevActiveInstance    
    // update __vue__ reference
    if (prevEl) {
      prevEl.__vue__ = null
    }    if (vm.$el) {
      vm.$el.__vue__ = vm
    }    
    // if parent is an HOC, update its $el as well
    if (vm.$vnode && vm.$parent && vm.$vnode === vm.$parent._vnode) {
      vm.$parent.$el = vm.$el
    }    
    // updated hook is called by the scheduler to ensure that children are
    // updated in a parent&#39;s updated hook.
  }
Nach dem Login kopieren

我们可以看到在如果_isMountedture的话(DOM已经被挂载)则会调用callHook(vm, &#39;beforeUpdate&#39;)方法,然后会对虚拟DOM进行重新渲染。然后在/src/core/observer/scheduler.js下的flushSchedulerQueue()函数中渲染DOM,在渲染完成调用callHook(vm, &#39;updated&#39;),代码如下:。

/**
 * Flush both queues and run the watchers.
 */function flushSchedulerQueue () { ...
  callUpdatedHooks(updatedQueue) ...}function callUpdatedHooks (queue) {
  let i = queue.length  while (i--) {
    const watcher = queue[i]
    const vm = watcher.vm    
    if (vm._watcher === watcher && vm._isMounted) {
      callHook(vm, &#39;updated&#39;)
    }
  }
}
Nach dem Login kopieren

当Vue实例需要进行销毁的时候回调beforeDestroy 、destroyed这两个函数钩子,它们的实现是在/src/core/instance/lifecycle.js下的Vue.prototype.$destroy中:

  Vue.prototype.$destroy = function () {
    const vm: Component = this    
    if (vm._isBeingDestroyed) {      
    return
    }
    callHook(vm, &#39;beforeDestroy&#39;)
    vm._isBeingDestroyed = true
    // remove self from parent
    const parent = vm.$parent
    if (parent && !parent._isBeingDestroyed && !vm.$options.abstract) {
      remove(parent.$children, vm)
    }    
    // teardown watchers
    if (vm._watcher) {
      vm._watcher.teardown()
    }
    let i = vm._watchers.length    
    while (i--) {
      vm._watchers[i].teardown()
    }    
    // remove reference from data ob
    // frozen object may not have observer.
    if (vm._data.__ob__) {
      vm._data.__ob__.vmCount--
    }    
    // call the last hook...
    vm._isDestroyed = true
    // invoke destroy hooks on current rendered tree
    vm.__patch__(vm._vnode, null)    
    // fire destroyed hook
    callHook(vm, &#39;destroyed&#39;)    
    // turn off all instance listeners.
    vm.$off()    
    // remove __vue__ reference
    if (vm.$el) {
      vm.$el.__vue__ = null
    }    
    // release circular reference (#6759)
    if (vm.$vnode) {
      vm.$vnode.parent = null
    }
  }
Nach dem Login kopieren

$destroy这个原型函数中,执行了Vue的销毁操作,我们可以看到在执行销毁操作之前调用了callHook(vm, &#39;beforeDestroy&#39;),然后执行了一系列的销毁操作,包括删除掉所有的自身(self)、_watcher、数据引用等等,删除完成之后调用callHook(vm, &#39;destroyed&#39;)

截止到这里,整个Vue生命周期图示中的所有生命周期钩子都已经被执行完成了。那么剩下的activated、deactivated、errorCaptured这三个钩子函数是在何时被执行的呢?我们知道这三个函数都是针对于组件(component)的钩子函数。其中activated、deactivated这两个钩子函数分别是在keep-alive 组件激活和停用之后回调的,它们不牵扯到整个Vue的生命周期之中activated、deactivated这两个钩子函数的实现代码都在/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, &#39;activated&#39;)
  }
}

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, &#39;deactivated&#39;)
  }
}
Nach dem Login kopieren

而对于errorCaptured来说,它是在2.5.0之后新增的一个钩子函数,它的代码在/src/core/util/error.js中:

export function handleError (err: Error, vm: any, info: string) {
  if (vm) {    let cur = vm    while ((cur = cur.$parent)) {      
  const hooks = cur.$options.errorCaptured      
  if (hooks) {        
  for (let i = 0; i < hooks.length; i++) {          
  try {            
  const capture = hooks[i].call(cur, err, vm, info) === false
            if (capture) return
          } catch (e) {
            globalHandleError(e, cur, &#39;errorCaptured hook&#39;)
          }
        }
      }
      
    }
  }
  globalHandleError(err, vm, info)
}function globalHandleError (err, vm, info) {
  if (config.errorHandler) {    
  try {      
  return config.errorHandler.call(null, err, vm, info)
    } catch (e) {
      logError(e, null, &#39;config.errorHandler&#39;)
    }
  }
  logError(err, vm, info)
}function logError (err, vm, info) {
  if (process.env.NODE_ENV !== &#39;production&#39;) {
    warn(`Error in ${info}: "${err.toString()}"`, vm)
  }  /* istanbul ignore else */
  if ((inBrowser || inWeex) && typeof console !== &#39;undefined&#39;) {
    console.error(err)
  } else {    
  throw err
  }
}
Nach dem Login kopieren

他是唯一一个没有通过callHook方法来执行的钩子函数,而是直接通过遍历cur(vm).$options.errorCaptured,来执行config.errorHandler.call(null, err, vm, info)的钩子函数。整个逻辑的结构与callHook使非常类似的。

截止到目前Vue中所有的生命周期钩子我们都已经介绍完成了,其中涉及到了一些源码的基础,是因为我觉得配合源码来一起看的话,会对整个Vue的运行过程有个更好的理解。大家一定要下载下来Vue的源代码,对照着我们的讲解来走一遍这个流程。

相关推荐:

vue生命周期、vue实例、模板语法

图概PHP生命周期,PHP生命周期

Das obige ist der detaillierte Inhalt vonVues Lebenszyklus und Quellcode-Implementierung (Code). Für weitere Informationen folgen Sie bitte anderen verwandten Artikeln auf der PHP chinesischen Website!

Verwandte Etiketten:
Quelle:php.cn
Erklärung dieser Website
Der Inhalt dieses Artikels wird freiwillig von Internetnutzern beigesteuert und das Urheberrecht liegt beim ursprünglichen Autor. Diese Website übernimmt keine entsprechende rechtliche Verantwortung. Wenn Sie Inhalte finden, bei denen der Verdacht eines Plagiats oder einer Rechtsverletzung besteht, wenden Sie sich bitte an admin@php.cn
Beliebte Tutorials
Mehr>
Neueste Downloads
Mehr>
Web-Effekte
Quellcode der Website
Website-Materialien
Frontend-Vorlage