背景私のコース「Vue 3 エンタープライズレベルの音楽アプリの開発」の Q&A セクションで、クラスメートが質問しました。歌手リストから歌手の詳細ページへの遷移アニメーションには、入場アニメーションのみがあり、退場アニメーションがありません。 学生は確かにしばらくこの問題に取り組んでいましたが、彼の説明からはしばらく問題が何なのかわからなかったので、コードを GitHub にアップロードするように依頼しました。結局のところ、コード レベルで直接問題を特定するのが最も信頼性が高いのです。 問題の場所通常、このような問題に遭遇したとき、私が最初に考えるのは、彼が使用している Vue 3 バージョンに問題があるのではないかということです。結局のところ、Vue 3 はまだ継続的な反復の過程にあり、特定のバージョンにいくつかの小さなバグがあるのは普通のことです。そこで、彼のプロジェクトの Vue 3 バージョンを最新の 3.2.26 にアップグレードしました。 しかし、実行してみると、問題がまだ存在していることがわかりました。少し混乱したので、コース プロジェクトのソース コードを実行しましたが、問題を再現できませんでした。その後、コース プロジェクトの Vue 3 バージョンを最新バージョンにアップグレードしましたが、それでも問題を再現できませんでした。 上記の分析を通じて、Vue 3 バージョンの問題は基本的に排除されました。基本的に、歌手ページから歌手詳細ページに切り替えることは、セカンダリ ルーティング ページである歌手詳細ページを開くことに過ぎず、歌手詳細ページから歌手ページに戻ることは、セカンダリ ルーティング ページである歌手詳細ページを削除することに過ぎません。そこで、2 つのプロジェクトの歌手ページと詳細ページのソース コードを比較し始めました。 <!-- 歌手.vue --> <テンプレート> <div class="歌手" v-loading="!singers.length"> <インデックスリスト :data="歌手" @select="歌手を選択" </インデックスリスト> <!-- セカンダリルーティングを実行するにはルータビューを使用します --> <!-- <ルータービュー:singer="選択された歌手"></ルータービュー>--> <!-- Vue3 はルータービューでトランジションを使用する必要があり、appear に入るとアニメーションが表示されます --> <router-view v-slot="{ コンポーネント }"> <!-- singer-detail はアニメーションの無効な調査を返します --> <transition appear name="スライド"> <!-- コンポーネント 動的コンポーネント コンポーネントは、スコープ スロットのプロパティで、router-view グループによって提供されます。 コンポーネントは、ルーティング テーブル内のルーティング コンポーネントです。 exclude="singer-detail" は、データをキャッシュしないコンポーネントを除外します。そうでない場合は、データがキャッシュされ、毎回再要求されることはありません --> <component :is="コンポーネント" :singer="選択した歌手" </コンポーネント> </トランジション> </ルータービュー> </div> </テンプレート> <!-- 歌手の詳細.vue --> <テンプレート> <!-- セカンダリ ルーティングを通じて実装されるため、ビューの下に配置されます --> <section class="歌手の詳細"> <音楽リスト :songs="曲" :title="タイトル" :pic="写真" :loading="読み込み中" </音楽リスト> </セクション> </テンプレート> 上記は学生のコードです。次に、私のプロジェクトのソース コードを貼り付けます。 <!-- 歌手.vue --> <テンプレート> <div class="歌手" v-loading="!singers.length"> <インデックスリスト :data="歌手" @select="歌手を選択" </インデックスリスト> <router-view v-slot="{ コンポーネント }"> <transition appear name="スライド"> <component :is="コンポーネント" :data="選択された歌手"/> </トランジション> </ルータービュー> </div> </テンプレート> <!-- 歌手の詳細.vue --> <テンプレート> <div class="歌手の詳細"> <音楽リスト :songs="曲" :title="タイトル" :pic="写真" :loading="読み込み中" </音楽リスト> </div> </テンプレート> 比較してみると、学生がコメントを使って勉強ノートを作っている点を除けば、両方のソースコードに大きな違いはないように感じます。最初は問題を見つけるのが難しかったので、ソース コードをデバッグするという最善の策を使いました。結局のところ、私は Vue 3 トランジションアニメーションの実装原則を非常によく知っています。 終了遷移アニメーションが実行されると、遷移コンポーネントによってラップされた子ノードから解析された Leave フック関数が実行されます。 そこで、Leave フック関数内にデバッガー ブレークポイントを追加しました。 // @vue/runtime-core/dist/runtime.core-bundler.esm.js 残す(el, 削除) { デバッガ 定数キー = String(vnode.key); el._enterCbの場合{ el._enterCb(true /* キャンセルされました */); } // ... } 次に、プロジェクトを実行します。歌手の詳細ページから歌手ページに戻ると、デバッガーのブレークポイントに入っていないことがわかります。これは、leave hook 関数がまったく実行されていないことを意味します。 さらに遡って、アンインストールしようとしているノードの場合、Leave Hook 関数が実行されるタイミングは、remove 関数の実行時なので、remove 関数内にブレークポイントを設定します。 // @vue/runtime-core/dist/runtime.core-bundler.esm.js 定数削除 = vnode => { デバッガ const { type、el、anchor、transition } = vnode; if (type === フラグメント) { フラグメントを削除します(el、アンカー); 戻る; } if (type === 静的) { staticNode を削除します(vnode); 戻る; } 定数実行削除 = () => { ホストを削除します(el); if (遷移 && !transition.persisted && transition.afterLeave) { 遷移後離れる(); } }; if (vnode.shapeFlag & 1 /* 要素 */ && 遷移 && !transition.persisted) { const { leave, delayLeave } = transition; const performLeave = () => leave(el, performRemove); (遅延離脱)の場合{ delayLeave(vnode.el、performRemove、performLeave); } それ以外 { 実行終了(); } } それ以外 { 削除を実行します(); } }; その後、プロジェクトを再度実行しました。歌手の詳細ページから歌手ページに戻ったとき、ブレークポイントに入ったにもかかわらず、コードにいくつかの論理的な問題があることがわかりました。対応する遷移オブジェクトが vnode から解析されました。対応するタイプは Fragment であるため、実行は次のロジックに入りました。 if (type === フラグメント) { フラグメントを削除します(el、アンカー); 戻る; } 後続の遷移オブジェクトのLeaveフック関数を実行せずに直接戻ります。引き続き vnode の値を確認したところ、コメント ノードとセクション ノードの 2 つの子ノードがあることがわかりました。突然、この問題は学生たちが書いたコメントによって引き起こされたことに気づきました。 <!-- 歌手の詳細.vue --> <テンプレート> <!-- セカンダリ ルーティングを通じて実装されるため、ビューの下に配置されます --> <section class="歌手の詳細"> <音楽リスト :songs="曲" :title="タイトル" :pic="写真" :loading="読み込み中" </音楽リスト> </セクション> </テンプレート> Vue のテンプレート解析で HTML コメントに遭遇すると、それもコメント ノードに解析されます。コンパイルされた結果を確認するには、Vue 3 テンプレート エクスポート ツールを使用できます。 import { createCommentVNode を _createCommentVNode として、resolveComponent を _resolveComponent として、createVNode を _createVNode として、createElementVNode を _createElementVNode として、Fragment を _Fragment として、openBlock を _openBlock として、createElementBlock を _createElementBlock として } from "vue" const _hoisted_1 = { クラス: "singer-detail" } 関数レンダリング(_ctx, _cache) { const _component_music_list = _resolveComponent("音楽リスト") 戻り値 (_openBlock(), _createElementBlock(_Fragment, null, [ _createCommentVNode("セカンダリルーティングを介して実装されるため、ビューの下に配置されます")、 _createElementVNode("セクション", _hoisted_1, [ _createVNode(_component_music_list, { 曲: _ctx.songs、 タイトル: _ctx.title, 画像: _ctx.pic, 読み込み中: _ctx.loading }, null, 8 /* PROPS */, ["songs", "title", "pic", "loading"]) ]) ], 2112 /* STABLE_FRAGMENT、DEV_ROOT_FRAGMENT */)) } Vue 3 は複数のルート ノードを持つテンプレートをサポートしているため、上記のテンプレートのルートは Fragment ノードに解析されます。つまり、コンポーネントが削除されたときに対応する遷移アニメーションは実行されません。 さらなる分析では、なぜフラグメント ノードには遷移アニメーションが必要ないのでしょうか?コードに対応するコミットコメントを見つけました:
コメントに記載されている説明によると、フラグメント ノードには遷移を設定できないということです。しかし、ここでまだ疑問が残ります。なぜこれを書いても遷移アニメーションに入ることに影響しないのでしょうか? コンポーネントのレンダリング関数が実行時に実行され、コンポーネントのサブツリー subTree がレンダリングされると、renderComponentRoot 関数内で特別な処理が実行されるためです。 関数renderComponentRoot(インスタンス) { 結果を出す // ... // 結果を取得するためにレンダリング関数を呼び出す // 属性のマージ // 開発モードではコメントは保持され、テンプレートで // ルート要素の横にコメントを付けてフラグメントにする ルート = 結果; setRoot = undefined とします。 ((process.env.NODE_ENV !== 'production') の場合 && 結果.patchFlag > 0 && result.patchFlag & 2048 /* DEV_ROOT_FRAGMENT */) { [ルート、setRoot] = getChildRoot(結果); } // 遷移データを継承する (vnode.transition) の場合 { // ... ルートの遷移 = vnode の遷移; } 結果を返す } コンポーネント インスタンスの render メソッドを実行してレンダリングされたサブツリーを取得した後、開発環境でコメント ノードが getChildRoot 関数を介してフィルタリングされ、結果のルートが取得され、そのルート ノードは親 vnode の遷移オブジェクトを継承します。ただし、renderComponentRoot 全体が依然として結果オブジェクトを返すことに注意してください。 例として挙げた SingerDetail 歌手詳細コンポーネントの場合、そのサブツリー vnode は Fragment ですが、renderComponentRoot を実行すると、最初のノードがコメント ノードであるためフィルタリングされ、後続のエンティティ ノード singer-detail に対応する vnode のみが transition 属性を持ち、遷移アニメーションに入ります。 ただし、コンポーネントが削除されると、コンポーネントのサブツリー vnode がフラグメントであるため、終了遷移アニメーションは実行されません。 要約するバグの原因がわかったら、修正は非常に簡単です。コメントノードを削除するだけです。もちろん、本番環境ではデフォルトでコメントノードが削除されるため、この問題は本番環境では発生しません。 このケースから、コメントを書くことは良い習慣ではあるものの、誤って Vue 3 の落とし穴に陥ってしまう可能性があることがわかります。 ソース コードをデバッグする方法を学ぶことは非常に重要です。ソース コードを理解していない場合、ドキュメントでは原因が説明されないため、そのようなバグに遭遇したときに混乱し、消極的になります。したがって、私は皆さんにソースコードをもっと勉強することを勧めます。ソースコードをデバッグすることで、真実に最も近づくことができます。 Vue3 トランジションアニメーションの落とし穴に関するこの記事はこれで終わりです。Vue3 トランジションアニメーションの落とし穴に関する関連記事をもっと知りたい場合は、123WORDPRESS.COM の過去の記事を検索するか、以下の関連記事を引き続きご覧ください。今後とも 123WORDPRESS.COM をよろしくお願いいたします。 以下もご興味があるかもしれません:
|
>>: Linux システムで MySQL の文字セットを UTF8 に変更する手順
公式サイト: http://code.google.com/p/zen-coding/ Zen コー...
Mysql マスタースレーブ サービスの実装例を構成する### メインデータベースmy.cnfを構成...
MySQLリモート接続の問題に関しては、会社で働いているときに誰かのコンピュータに保存されているMy...
ワーカープロセスは、起動されると、まず自身の動作に必要な環境を初期化し、次に実行する必要があるイベン...
目次概要ジェネリック医薬品とはビルドシステムジェネリック医薬品の一般的な理解ジェネリッククラスジェネ...
MySql Nullフィールド判定とIFNULL失敗処理ps: (プロセスを表示したくない場合は、S...
今日、redis をインストールしたところ、今までになかったいくつかのエラーが発生しました。ここで記...
MySQL レプリケーションには、SQL ステートメント ベースのレプリケーション (SBR)、行ベ...
前の 2 つの章を終えて、ボタンのフローティング アニメーションについて新たな理解が得られましたか?...
サブクエリの分類返された結果セットによる分類サブクエリは、返される結果セットの違いに応じて、テーブル...
方法1: CSSオーバーフロー省略を使用して解決する解決策は次のとおりです。 CSSコード: ディス...
auto.js を使用して毎日のチェックインを自動化する感染症のせいで、毎日時間通りに家に帰らなけれ...
Safari (Technology Preview 106) および Firefox (バージョン...
入力ボックスの値を取得する複数の方法最初の方法は、制御されていないコンポーネントの取得です2番目の方...
1. ダウンロード1. インストールパッケージをダウンロードするMySQL ダウンロード パス: h...