この記事は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 における SUID、SGID、SBIT の素晴らしい使い方の詳細な説明

序文Linux のファイル権限管理はとにかく素晴らしいです。SUID、SGID、SBIT の機能を確...

ウェブサイトのビジュアルデザイン(画像とテキスト)における情報伝達の役割と方法

現代の Web ビジュアル デザインは、初期の情報の積み重ねから、その後のグラフィックスと抽象化、そ...

VueRouterルーティングの詳細な説明

目次vueルーター1. ルーティングの概念を理解する1.1 ルーティングとは何ですか? 1.2. バ...

MySQL のソート関数 field() の詳細な例

序文私たちの日常の開発プロセスでは、ソートが頻繁に使用され、そのような要求がある場合もあります。たと...

Dockerに証明書を追加する方法

1. アップグレードプロセス: sudo apt-get updateパッケージが見つからない、パッ...

MySQL マスタースレーブ構成の学習ノート

● 新しいプロジェクトのセキュリティを確保するためにクラウド データを購入する予定でした。 Alib...

Centos7 での DNS サーバーの構築の概要

目次1. プロジェクト環境: 2: DNSサーバーの設定i: 前方解析を構成する: ii: 逆解像度...

Vueのsync修飾子の詳細な説明

目次1. 手順2. 修飾語3. .sync 修飾子4. まとめ1. 手順指示とは命令です。文字通りの...

Vue3 を使用してアップロード コンポーネントを実装するためのサンプル コード

目次一般的なアップロードコンポーネントの開発以下の機能を実装する必要がありますカスタムテンプレートサ...

MySQL 中断された接続警告ログの分析

序文:場合によっては、MySQL に接続されたセッションが異常終了することが多く、エラー ログに「通...

MySQL 8.0 バージョンで getTables がすべてのデータベース テーブルを返す問題の簡単な分析

序文この記事では、主にライブラリ内のすべてのテーブルを返すMysql8.0ドライバgetTables...

Vue プロジェクトで mock.js を使用するための完全な手順

Vue プロジェクトで mock.js を使用する開発ツールの選択: Vscode 1. コマンドラ...

TOM.COMのホームページリニューアルの経験

<br />何の警告もなく、cnBeta で TOM.COM の Web サイトが再設計...

トランザクション分離レベルのMySQLケース分析

目次1. 理論シリアル化可能繰り返し読み取りコミットされた読み取りコミットされていない読み取り2. ...

WeChat アプレットのカスタム タブバー コンポーネント

この記事では、WeChatアプレットのカスタムタブバーコンポーネントの具体的なコードを参考までに紹介...