Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Fix: PitchLineの初期化をonMountedOrActivatedで行っていなかったので修正 #2558

Open
wants to merge 4 commits into
base: main
Choose a base branch
from

Conversation

sigprogramming
Copy link
Contributor

内容

PitchLineの初期化をonMountedOrActivatedで行っていなかったので修正します。
(ピッチを表示した状態でソング→トーク→ソングと切り替えるとエラーになるのを修正します)

また、以下も行います。

  • トーク/ソングの切り替えでPIXI(WebGL)のオブジェクトを破棄しないように(維持するように)する
    • onMountedOrActivatedからonMountedに変更
    • 問題なく動くのと、パフォーマンスにも影響しないと思うので

その他

@sigprogramming sigprogramming requested a review from a team as a code owner February 24, 2025 07:02
@sigprogramming sigprogramming requested review from Hiroshiba and removed request for a team February 24, 2025 07:02
@voicevox-preview-pages
Copy link

voicevox-preview-pages bot commented Feb 24, 2025

🚀 プレビュー用ページを作成しました 🚀

更新時点でのコミットハッシュ:267335d

Copy link
Member

@Hiroshiba Hiroshiba left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

トーク/ソングの切り替えでPIXI(WebGL)のオブジェクトを破棄しないように(維持するように)する
onMountedOrActivatedからonMountedに変更

これはアリだと思います!
もちろんメモリ消費は多めになりそうですが、トーク←→ソングの切り替えスピードも上がると思うのと、onMountedやonActivated周り簡単になりそうなので!

たぶんonMountedに変えたことでいろいろ前提が変わってより簡単にできそうだったので、ちょっと気になった点をコメントしました!

renderInNextFrame = true;
};

let initialized = false;
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

状態変数が多く、起動シーケンスが結構ややこしくなっているので、可能なら削減できると嬉しいかもです!

initializedがあるのはwatch { immediate: true }時に発動させないためだと思います。
となるとたぶん{ immediate: true }を消せばinitializedをなくせそうですがどうでしょう・・・?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

immediate: trueは必要なさそうですが、immediate: falseのときでもwatchのコールバックがonMountedの前に呼ばれるというのはタイミングによっては起こり得るので(たぶん)、initializedフラグはあった方が安全かなと思います。
ひとまずimmediate: trueは無くしました。

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

たしかに!!!
起動シーケンスややこしくなっちゃうなと思ってドキュメント読み直してたら、必ずonMountedの後にwatchコールバックが呼ばれそうな設定がありました!!
https://ja.vuejs.org/guide/essentials/watchers.html#post-watchers

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

すみません、不正確でした。。

flush: "post"に関係なく、たぶんonMountedの前にwatchが呼ばれることはimmediate: true以外ではなさそうでした!
Qiita記事にまとめてみました。

KeepAliveとかv-if含めてガチャガチャいろいろ検証してみた感じでも、watchが呼ばれるのは必ずonMountedよりは後でした!!
Playgroundこちらです。

Comment on lines +392 to +394
// NOTE: watchのimmediateはonMountedの前に実行されるので、最初の更新はwatchではなくここで直接実行する
void updateOriginalPitchLineDataMap();
void updatePitchEditLineDataMap();
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

現状、念の為に呼んでる感じ・・・・・でしょうか・・・?
データが更新されるたびにupdateOriginalPitchLineDataMap等が呼ばれるので、データが更新されていないはずのonMounted内では呼ばなくても良いはず・・・?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

PitchLine.pitchDataMapは最初は空なので、updateOriginalPitchLineDataMap等を呼んでPitchLine.pitchDataMapを更新(値をセット)する必要があります。

Copy link
Member

@Hiroshiba Hiroshiba Feb 25, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

たぶんupdateOriginalPitchLineDataMapを呼んでるwatchwatch([singingGuidesInSelectedTrack, tempos, tpqn]は、データが空っぽじゃなくなったタイミングで必ず実行されるので、onMountedで明示的に呼ばなくても値がちゃんとセットされる気がします!

質問の意図は、例えば万が一このコンポーネントのonMountedが2度以上呼ばれるようになると、ここでupdate関数を叩かないといけないので、念の為に呼ぶ意図なのかな〜と思った次第です。

onMountedでupdate呼ぶのは良いと思うのですが、値を同期させる意図なのであればwatch内でやったほうが起動シーケンスが簡単になるんですよねー・・・。
ということで、watchImmediateAfterMountedみたいなコンポーザブルを作るのはどうでしょうか!
こんな感じの関数を作ればよいのかなと!
onMounted後にコールバックが必ず実行される・・・はず・・・? ちょっと関数名はもう少しマシ名の思いつきたいかも。。

import { WatchSource, watch, ref, onMounted } from "vue";

const watchImmediateAfterMounted = <T>(
  source: WatchSource<T>,
  fn: (after: T, before: T) => void,
) => {
  // onMountedのときにtrueになるだけのref
  const mounted = ref(false);
  onMounted(() => {
    mounted.value = true;
  });

  // watchしたいものと`mounted`をwatchする
  watch([source, mounted], ([after, mounted], [before]) => {
    if (mounted) fn(after, before); // onMounted後に必ず1回実行される
  });
};

export default watchImmediateAfterMounted;

ちなみにonetimeWatchを参考にしました!
https://github.com/VOICEVOX/voicevox/blob/94995bf76da3bd06169f4de128803b00ee83b5ab/src/helpers/onetimeWatch.ts

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

2 participants