背景私のコース「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 に変更する手順
Nginx は、リバース プロキシ機能を使用して負荷分散を実装できるほか、フォワード プロキシ機能を...
序文Vue(発音は /vjuː/、view に似ています)は、ユーザーインターフェイスを構築するため...
1. 事件の背景:仕事上、Ubuntu への vscode リモート接続を使用する必要があります。 ...
コードをコピーコードは次のとおりです。 <!DOCTYPE html PUBLIC "...
履歴コマンドを表示し、指定されたコマンドを実行します owen@owen:~/owen/softwa...
この記事では、動的なテーブル効果を実現するためのJavaScriptの具体的なコードを参考までに紹介...
相対幅と絶対幅が競合する場合のdivソリューション概要: 一般的に、絶対幅を使用する場合は px を...
アーティストになるつもりがない場合は、開発者として HTML を読んで、必要に応じて簡単な変更を加え...
この記事は、この時期の「ピーターから奪ってポールに払う」という仕事のスタイルに対する私の不満から生ま...
この記事では、クリック時にサブメニューを表示するためのJavaScriptの具体的なコードを参考まで...
1. 実験環境シリアルナンバープロジェクトソフトウェアとバージョン1オペレーティング·システムCen...
古典的な色の組み合わせは力と権威を伝え、強いロイヤルブルーはあらゆる古典的な色の組み合わせの中心的な...
今日、PHP を学習する場合、当然ながら、まず実行環境をインストールする必要があります。Phpstu...
まとめシナリオによっては、レコードがない場合は挿入し、レコードがある場合は更新するという要件がある場...
1. 切断理由WebSocket が切断される理由は多数あります。WebSocket が切断されたと...