この記事はVueのライフサイクルを理解するのに役立ちます

この記事はVueのライフサイクルを理解するのに役立ちます

序文:

Vueインスタンスは、作成前に一連の初期化プロセスを経ます。たとえば、データ監視を設定し、テンプレートをコンパイルし、インスタンスを DOM にマウントし、データが変更されたときにDOMを更新する必要があります。同時に、ライフサイクル フックと呼ばれるいくつかの関数もこのプロセス中に実行され、ユーザーは特定のシナリオで独自のコードを追加できるようになります。

ソース コード内で最終的にライフサイクルを実行する関数はすべて、 src/core/instance/lifecycleで定義されているcallHookメソッドを呼び出します。

関数 callHook (vm: コンポーネント、フック: 文字列) をエクスポートします。
 // #7573 ライフサイクルフックを呼び出すときに依存関係コレクションを無効にする
  プッシュターゲット()
  const ハンドラ = vm.$options[フック]
  if (ハンドラ) {
    (i = 0、j = handlers.length; i < j; i++) の場合 {
      試す {
        ハンドラ[i].call(vm)
      } キャッチ (e) {
        handleError(e, vm, `${hook} フック`)
      }
    }
  }
  (vm._hasHookEvent)の場合{
    vm.$emit('フック:' + フック)
  }
  ポップターゲット()
}


callHook関数のロジックは非常にシンプルです。渡された文字列 hook に従って、 vm.$options[hook]に対応するコールバック関数配列を取得し、それを走査して実行します。実行時には、関数実行のコンテキストとして vm が使用されます。

1. beforeCreate & created

Vue がインスタンス化されるとき、 beforeCreate関数とcreated関数の両方が _init メソッドで実行されます。これはsrc/core/instance/init.jsで定義されています。

Vue.prototype._init = 関数 (オプション?: オブジェクト) {
  // ...
  ライフサイクルの初期化(vm)
  イベントの初期化(vm)
  レンダリングの初期化(vm)
  フックを呼び出します(vm、'beforeCreate')
  initInjections(vm) // データ/プロパティの前にインジェクションを解決する
  初期化状態(vm)
  initProvide(vm) // data/props の後に provide を解決する
  callHook(vm, '作成済み')
  // ...
}


beforeCreatecreatedのフック呼び出しがinitState前後にあることがわかります。 initStateの機能は、 propsdatamethodswatchcomputedなどのプロパティを初期化することです。これらについては後で詳しく分析します。当然ですが、 beforeCreateフック関数はpropsdataで定義された値を取得することはできず、 methodsで定義された関数を呼び出すこともできません。

これら 2 つのフック関数が実行されると、DOM はレンダリングされないため、DOM にアクセスできません。一般的に、コンポーネントがロード時にバックエンドと対話する必要がある場合は、これら 2 つのフック関数で実行できます。 propsdataなどのデータにアクセスする必要がある場合は、 createdフック関数を使用する必要があります。後でvue-routerと vuex を紹介するときに、両方でbeforeCreatdフック関数が混在していることがわかります。

2. マウント前とマウント済み

名前が示すように、 beforeMountフック関数はmountで、つまり DOM がマウントされる前に実行されます。これは、 src/core/instance/lifecycle.jsで定義されているmountComponent関数で呼び出されます。

エクスポート関数mountComponent(
  vm: コンポーネント、
  el: ?要素、
  水分補給?: ブール値
): 成分 {
  vm.$el = el
  // ...
  callHook(vm, 'beforeMount')
 
  コンポーネントを更新します
  /* イスタンブールは無視します */
  process.env.NODE_ENV !== 'production' && config.performance && mark の場合 {
    更新コンポーネント = () => {
      定数名 = vm._name
      定数 id = vm._uid
      const startTag = `vue-perf-start:${id}`
      const endTag = `vue-perf-end:${id}`
 
      マーク(開始タグ)
      定数 vnode = vm._render()
      マーク(終了タグ)
      measure(`vue ${name} render`, startTag, endTag)
 
      マーク(開始タグ)
      vm._update(vnode、ハイドレーション)
      マーク(終了タグ)
      measure(`vue ${name} patch`, startTag, endTag)
    }
  } それ以外 {
    更新コンポーネント = () => {
      vm._update(vm._render(), ハイドレーション)
    }
  }
 
  // ウォッチャーのコンストラクタ内でこれを vm._watcher に設定します
  // ウォッチャーの初期パッチは$forceUpdateを呼び出す可能性があるので(例えば、子プロセス内で)、
  // コンポーネントのマウントされたフック)、これはvm._watcherが既に定義されていることに依存します
  新しいウォッチャー(vm、updateComponent、noop、{
    前に () {
      (vm._isMounted) の場合 {
        callHook(vm, 'beforeUpdate')
      }
    }
  }, true /* isRenderWatcher */)
  水分補給 = 偽
 
  // 手動でマウントされたインスタンス、自身にマウントされた呼び出し
  // マウントは、挿入されたフック内のレンダリングによって作成された子コンポーネントに対して呼び出されます
  (vm.$vnode == null)の場合{
    vm._isMounted = true
    callHook(vm, 'マウント済み')
  }
  戻り値
}


vm. render()関数を実行して VNode をレンダリングする前に、 beforeMountフック関数が実行されますvm. update() VNode patch後、 moutedフックが実行されます。注意すべきは、 moutedフック関数の実行には判断ロジックがあるということです。vm vm.$vnodeが null の場合、これはコンポーネントの初期化プロセスではなく、外部のnew Vueを介した初期化プロセスであることを意味します。では、コンポーネントはいつmountedのでしょうか?

コンポーネントのVNode patch後、 invokeInsertHook関数が実行され、 insertedVnodeQueueに保存されたフック関数が 1 つずつ実行されます。これはsrc/core/vdom/patch.jsで定義されています。

関数invokeInsertHook(vnode、キュー、初期値){
 // コンポーネントルートノードの挿入フックを遅延し、
  // 要素が実際に挿入されます
  if (isTrue(initial) && isDef(vnode.parent)) {
    vnode.parent.data.pendingInsert = キュー
  } それ以外 {
    (i = 0; i < キューの長さ; ++i) の場合 {
      キュー[i].data.hook.insert(キュー[i])
    }
  }
}


この関数はinsertフック関数を実行します。コンポーネントの場合、挿入フック関数はsrc/core/vdom/create-component.jscomponentVNodeHooksで定義されています。

定数componentVNodeHooks = {
  // ...
  挿入 (vnode: MountedComponentVNode) {
    const { コンテキスト、コンポーネントインスタンス } = vnode
    コンポーネントインスタンスがマウントされている場合
      コンポーネントインスタンス._isMounted = true
      callHook(componentInstance, 'マウント済み')
    }
    // ...
  },
}


このフック関数では、各子コンポーネントがmoutedフック関数を実行していることがわかります。また、 insertedVnodeQueue追加する順序は、最初に子、次に親であることが以前に分析されているため、同期的にレンダリングされる子コンポーネントの場合、 mountedフック関数の実行順序も最初に子、次に親になります。

3. beforeUpdate と updated

名前が示すように、 beforeUpdateupdatedフック関数の実行タイミングは、データが更新されたときである必要があります。これまで、 Vueのデータ双方向バインディングと更新を分析していませんでした。次の章でこの処理を詳しく紹介します。

beforeUpdateの実行時間は、 Watcherのレンダリングのbefore関数内にあります。

エクスポート関数mountComponent(
  vm: コンポーネント、
  el: ?要素、
  水分補給?: ブール値
): 成分 {
  // ...
 
  // ウォッチャーのコンストラクタ内でこれを vm._watcher に設定します
  // ウォッチャーの初期パッチは$forceUpdateを呼び出す可能性があるので(例えば、子プロセス内で)、
  // コンポーネントのマウントされたフック)、これはvm._watcherが既に定義されていることに依存します
  新しいウォッチャー(vm、updateComponent、noop、{
    前に () {
      (vm._isMounted) の場合 {
        callHook(vm, 'beforeUpdate')
      }
    }
  }, true /* isRenderWatcher */)
  // ...
}


ここで判断が行われることに注意してください。つまり、このフック関数はコンポーネントがmountedれた後にのみ呼び出されます。

updateの実行時間は、 src/core/observer/scheduler.jsで定義されているflushSchedulerQueue関数が呼び出されたときです。

関数flushSchedulerQueue() {
  // ...
  // 更新されたキューを取得する
  更新されたフックを呼び出します(更新されたキュー)
}
 
関数callUpdatedHooks(キュー){
  i = キューの長さとする
  (i--) {
    const ウォッチャー = キュー[i]
    定数 vm = ウォッチャー.vm
    (vm._watcher === ウォッチャー && vm._isMounted) の場合 {
      callHook(vm, '更新')
    }
  }
}


flushSchedulerQueue関数については後ほど詳しく説明しますが、まずは概要を理解しておいてください。updatedQueue は更新されたwathcerの配列です。callUpdatedHooks 関数では、これらの配列を走査します。 updated updatedQueue callUpdatedHooksは、現在のwatchervm._watcherであり、コンポーネントがmountedている場合にのみ実行されます。

前にも述べたように、コンポーネントのmountプロセス中に、レンダリングWatcherがインスタンス化され、VM 上のデータの変更を監視して再レンダリングします。このロジックはmountComponent関数が実行されたときに発生します。

エクスポート関数mountComponent(
  vm: コンポーネント、
  el: ?要素、
  水分補給?: ブール値
): 成分 {
  // ...
  // これは省略形です let updateComponent = () => {
      vm._update(vm._render(), ハイドレーション)
  }
  新しいウォッチャー(vm、updateComponent、noop、{
    前に () {
      (vm._isMounted) の場合 {
        callHook(vm, 'beforeUpdate')
      }
    }
  }, true /* isRenderWatcher */)
  // ...
}


次に、 Watcherをインスタンス化するプロセスで、 isRenderWatcherそのコンストラクターで判断され、現在のwatcherインスタンスがsrc/core/observer/watcher.jsで定義されているvm._watcherに割り当てられます。

デフォルトクラスWatcherをエクスポートします{
  // ...
  コンストラクタ(
    vm: コンポーネント、
    expOrFn: 文字列 | 関数、
    cb: 機能、
    オプション?: ?オブジェクト、
    isRenderWatcher?: ブール値
  ){
    this.vm = vm
    if (isRenderWatcher) {
      vm._watcher = これ
    }
    vm._watchers.push(これ)
    // ...
  }
}


同時に、現在のwathcerインスタンスがvm. watchersにプッシュされますvm. watcher 、vm 上のデータの変更を監視して再レンダリングするために特に使用されるため、レンダリング関連のwatcherです。そのため、 callUpdatedHooks関数では、 vm._watcherのコールバックが実行された後にのみ、 updatedフック関数が実行されます。

4. beforeDestroyとdestroy

名前が示すように、 beforeDestroy およびdestroyedフック関数,beforeDestroyコンポーネントの破壊の段階です。コンポーネントの破壊プロセスについては後で詳しく説明しますが、最後に $ destroyメソッドが呼び出されます。これはsrc/core/instance/lifecycle.jsで定義されています。

Vue.prototype.$destroy = 関数 () {
    const vm:コンポーネント = this
    (vm._isBeingDestroyed)の場合{
      戻る
    }
    callHook(vm, 'beforeDestroy')
    vm._isBeingDestroyed = true
    // 親から自分自身を削除する
    定数親 = vm.$parent
    if (親 && !parent._isBeingDestroyed && !vm.$options.abstract) {
      削除(親.$children, vm)
    }
    // ティアダウンウォッチャー
    (vm._watcher)の場合{
      vm._watcher.ティアダウン()
    }
    i = vm._watchers.length とします。
    (i--) {
      vm._watchers[i].ティアダウン()
    }
    // データオブジェクトから参照を削除する
    // 凍結されたオブジェクトにはオブザーバーがない可能性があります。
    (vm._data.__ob__)の場合{
      vm._data.__ob__.vmCount--
    }
    // 最後のフックを呼び出します...
    vm._isDestroyed = 真
    // 現在レンダリングされているツリーの破棄フックを呼び出す
    vm.__patch__(vm._vnode、null)
    // 火で破壊されたフック
    callHook(vm, '破棄されました')
    // すべてのインスタンス リスナーをオフにします。
    vm.$オフ()
    // __vue__ 参照を削除
    (vm.$el)の場合{
      vm.$el.__vue__ = null
    }
    // 循環参照を解除する (#6759)
    (vm.$vnode) の場合 {
      vm.$vnode.parent = null
    }
  }


beforeDestroyフック関数は、 destroy関数実行の最初に実行され、 parentchildrenからの自身の削除、 watcherの削除、現在レンダリングされているVNodeの破棄フック関数の実行など、一連の破棄アクションを実行します。実行が完了すると、 destroyフック関数が再度呼び出されます。

$destroy の実行中に、 vm. patch (vm._vnode, null)が実行され、その子コンポーネントの破棄フック関数がトリガーされます。そのため、再帰呼び出しはレイヤーごとに行われ、 destroyフック関数の実行順序は、マウントされたプロセスと同じように、最初に子、次に親の順になります。

5. 有効化と無効化

activated およびdeactivatedフック関数はkeep-aliveコンポーネント用に特別にカスタマイズされたフックです。keep keep-aliveコンポーネントの紹介時に詳しく紹介しますので、ここでは保留にしておきます。

要約:

このセクションでは、主に Vue ライフサイクルにおける各フック関数の実行タイミングと順序を紹介します。分析により、 createdフック関数でデータにアクセスし、 mountedフック関数で DOM にアクセスし、 destroyフック関数でタイマーによる破棄作業を実行できることがわかります。これらを理解することで、適切なライフサイクルでさまざまなことを行うことができます。

Vue のライフサイクルを理解するためのこの記事はこれで終わりです。Vue のライフサイクルに関するその他のコンテンツについては、123WORDPRESS.COM の過去の記事を検索するか、以下の関連記事を引き続き参照してください。今後とも 123WORDPRESS.COM をよろしくお願いいたします。

以下もご興味があるかもしれません:
  • Vueライフサイクルの違いの詳細な説明
  • Vue.js の計算プロパティ、監視プロパティ、ライフサイクルの詳細な説明
  • Vue フィルター、ライフサイクル関数、vue-resource の簡単な紹介
  • Vueライフサイクルの詳細な理解
  • Vueコンポーネントライフサイクルの動作原理の分析
  • Vueライフサイクルを有効にすると、データ操作を再要求せずに前のページに戻ります。
  • Vue のプロパティ、メソッド、ライフサイクルのサンプルコードの詳細な説明
  • Vueライフサイクル操作の例
  • Vuex を Vue ライフサイクルに注入するプロセスについての簡単な説明
  • Vue ライフサイクルの調査
  • Vue js のライフサイクル(読めばわかります)(推奨)
  • Vue ライフサイクルとフック関数の簡単な例

<<:  MySQL 使用仕様の概要

>>:  Dockerを使用して完全な開発環境を構築するための詳細なチュートリアル

推薦する

Linux での fuser コマンドの使用法の詳細な説明

説明する: fuser は、現在ディスク上のファイル、マウント ポイント、さらにはネットワーク ポー...

MySQL の null 制約のケースの説明

目次テーブルを作成するときにNOT NULL制約を設定するテーブルを変更するときに非NULL制約を追...

MySQL をベースにしたシンプルな検索エンジンを実装する

目次MySQL ベースの検索エンジンの実装1. ngram全文パーサー2. 全文インデックスを作成す...

Linuxネットワーク設定の基本操作コマンドを詳しく解説

目次ネットワーク構成を表示するネットワークインターフェース情報を表示する---ifconfigルーテ...

Vue3.0 で Vuex 状態管理を開始する方法をすぐに習得します

Vuex は、Vue.js アプリケーション専用に開発された状態管理パターンです。集中型ストレージを...

MySQLクエリのパフォーマンスを分析する方法

目次スロークエリの基礎: データ取得の最適化データベースから不要なデータが要求されていないか確認する...

Dockerfile を使用して Docker でイメージを構築する方法

イメージを構築するこれまで、テストやデモンストレーションにさまざまなイメージを使用しました。多くの場...

Mysql と Oracle でよく使用される複数テーブルの変更ステートメントの概要

今日、SQLトレーニングの質問バンクでこの質問を見ました。これは、非常に代表的なマルチテーブル変更の...

MySQL の日付と時刻の加算と減算のサンプル コード

目次1.MySQLは時間間隔を加算または減算します2. 日付を減算する最近、MySQL を見直してい...

VueはAmapを使用して都市の位置特定を実現

この記事では、Amapを使用して都市の位置特定を実現するVueの具体的なコードを参考までに共有します...

js の parseInt() の奇妙な動作の調査と修正

背景: parseInt(0.006) または parseInt(0.0006) は 0 という値を...

CentOS7.6 システムで yum を使用して lnmp 環境を構成する方法

1. インストールバージョンの詳細 サーバー: MariaDB サーバーバージョン: 5.5.60-...

MySQL 8.0.15 圧縮版インストール グラフィック チュートリアル

この記事では、参考までにMySQL 8.0.15圧縮版のインストール方法を紹介します。具体的な内容は...

MySql8 WITH RECURSIVE 再帰クエリ親子コレクションメソッド

背景コメントに似た機能を開発する場合は、必要に応じてすべてのコメントのサブセットをクエリする必要があ...

JSはストップウォッチタイマーを実装します

この記事の例では、ストップウォッチタイマーを実装するためのJSの具体的なコードを参考までに共有してい...