Skip to content

optimize: VueUse を用いてグローバルなイベント監視を効率化する#4890

Merged
uni-kakurenbo merged 13 commits intomasterfrom
optimize/effect-scope
Dec 30, 2025
Merged

optimize: VueUse を用いてグローバルなイベント監視を効率化する#4890
uni-kakurenbo merged 13 commits intomasterfrom
optimize/effect-scope

Conversation

@uni-kakurenbo
Copy link
Contributor

@uni-kakurenbo uni-kakurenbo commented Oct 28, 2025

なぜこの PR を入れたいのか

動作確認の手順

  • 実際に使ってみて、現在の挙動と差異がないことを確かめる

PR を出す前の確認事項

  • 動作確認ができている
  • 自分で一度コードを眺めて自分的に問題はなさそう

@github-actions
Copy link

@uni-kakurenbo uni-kakurenbo changed the title optimize & refactor: window に対するイベント監視を、参照カウントと Effect Scope を用いて効率化する optimize & refactor: 参照カウントと Effect Scope を用いて window に対するイベント監視を効率化する Oct 28, 2025
@uni-kakurenbo uni-kakurenbo changed the title optimize & refactor: 参照カウントと Effect Scope を用いて window に対するイベント監視を効率化する optimize & refactor: 参照カウントと Effect Scope を用いてグローバルなイベント監視を効率化する Oct 28, 2025
@codecov
Copy link

codecov bot commented Oct 28, 2025

Codecov Report

❌ Patch coverage is 14.28571% with 6 lines in your changes missing coverage. Please review.
✅ Project coverage is 60.81%. Comparing base (ecb0d1d) to head (c0cf29d).
⚠️ Report is 14 commits behind head on master.

Files with missing lines Patch % Lines
src/composables/dom/useInsertText.ts 0.00% 5 Missing ⚠️
src/lib/basic/array.ts 50.00% 1 Missing ⚠️
Additional details and impacted files
@@            Coverage Diff             @@
##           master    #4890      +/-   ##
==========================================
- Coverage   61.01%   60.81%   -0.20%     
==========================================
  Files         101      101              
  Lines        2970     2973       +3     
  Branches      615      616       +1     
==========================================
- Hits         1812     1808       -4     
- Misses       1061     1071      +10     
+ Partials       97       94       -3     

☔ View full report in Codecov by Sentry.
📢 Have feedback on the report? Share it here.

🚀 New features to boost your workflow:
  • ❄️ Test Analytics: Detect flaky tests, report on failures, and find test suite problems.
  • 📦 JS Bundle Analysis: Save yourself from yourself by tracking and limiting bundle sizes in JS merges.

@uni-kakurenbo uni-kakurenbo changed the title optimize & refactor: 参照カウントと Effect Scope を用いてグローバルなイベント監視を効率化する optimize: 参照カウントと Effect Scope を用いてグローバルなイベント監視を効率化する Oct 28, 2025
@uni-kakurenbo uni-kakurenbo self-assigned this Oct 28, 2025
@uni-kakurenbo uni-kakurenbo force-pushed the optimize/effect-scope branch 2 times, most recently from 14fa6b5 to 3dd0f11 Compare October 28, 2025 15:21
@uni-kakurenbo uni-kakurenbo added refactor optimize performance optimization labels Oct 29, 2025
@uni-kakurenbo uni-kakurenbo moved this from Inbox to In review in traQ Client Oct 29, 2025
@uni-kakurenbo uni-kakurenbo moved this from In review to In progress in traQ Client Oct 29, 2025
@uni-kakurenbo uni-kakurenbo force-pushed the optimize/effect-scope branch 3 times, most recently from 64e6323 to 18dcfc4 Compare October 29, 2025 15:03
@uni-kakurenbo uni-kakurenbo force-pushed the optimize/effect-scope branch 3 times, most recently from 10e8153 to 68df132 Compare December 29, 2025 07:37
Copy link
Contributor

@cp-20 cp-20 left a comment

Choose a reason for hiding this comment

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

ありがとう

いくつかコメントしたけど、概ね良いと思います

Comment on lines +26 to +27
// eslint-disable-next-line @typescript-eslint/no-non-null-assertion
return state!
Copy link
Contributor

Choose a reason for hiding this comment

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

non-null というよりは as ReturnType<Fn> な気がしたけど、どうだろう (Fn に何が入るのか分からない以上 null が返ってくるかもしれない)

Copy link
Contributor Author

Choose a reason for hiding this comment

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

たしかにです
そうします

Comment on lines +7 to +9
export function unrefElement<T>(
element: MaybeRefOrGetter<T>
): UnrefElementReturn<T>
Copy link
Contributor

Choose a reason for hiding this comment

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

シグネチャを分けてる意味ある? (関数オーバーロード?)

Copy link
Contributor Author

Choose a reason for hiding this comment

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

だいぶ前に書いた部分なので忘れてしまったのですが、たぶんない気がしたので直します

Comment on lines +39 to +42
_targets: MaybeRefOrGetter<MaybeArray<Target> | null | undefined>,
_events: MaybeRefOrGetter<MaybeArray<EventNames<Target>>>,
_handlers: MaybeRef<MaybeArray<EventListenerType<EventType>>>,
options?: MaybeRefOrGetter<boolean | AddEventListenerOptions>
Copy link
Contributor

Choose a reason for hiding this comment

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

_ の prefix をつけるより argment であることを示した方が良いかも (_ の prefix は未使用変数に付けるのが慣例的な気がしている)

import useEventListener from './dom/useEventListener'

const useResponsive = () => {
const queryList = window.matchMedia(`(max-width: ${mobileMinBreakpoint}px)`)
Copy link
Contributor

Choose a reason for hiding this comment

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

この変更の本質ではないけど、なんで queryList って命名なんだろう

Copy link
Contributor Author

Choose a reason for hiding this comment

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

ここは過去のコードから引き継いだ部分なので定かではないのですが、window.matchMedia が返すのが MediaQueryList だからな気がします

Comment on lines +40 to +42
_targets: MaybeRefOrGetter<MaybeArray<Target> | null | undefined>,
_events: MaybeRefOrGetter<MaybeArray<EventNames<Target>>>,
_handlers: MaybeRef<MaybeArray<EventListenerType<EventType>>>,
Copy link
Contributor

Choose a reason for hiding this comment

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

これらが MaybeArray を受け取るのはなんでですか? (見た感じ array で受け取っている箇所はなさそう?)

Copy link
Contributor Author

Choose a reason for hiding this comment

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

VueUse の useEventListener が MaybeArray を受け付けていたので、使用感がそろっていたほうが嬉しいかと思ってそのようにしました。

Copy link
Contributor

Choose a reason for hiding this comment

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

なるほど、、、 合わせても良いけど、実装が複雑になるし実際使うことはほぼない気がするから (配列にするときはその分だけ useEventListener を呼び出せばよい) 配列を受け取らなくても良い気がするな

Copy link
Contributor Author

Choose a reason for hiding this comment

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

確かにです、そうします
(と思ったのですがそもそも VueUse を導入してしまってもよさそう....?)

Copy link
Contributor

Choose a reason for hiding this comment

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

まかせます

Copy link
Contributor Author

Choose a reason for hiding this comment

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

わざわざこっちでメンテナンスする理由が特に思い浮かばないのと、他にも VueUse で置換できそうな部分があったので VueUse を導入しました

Comment on lines -114 to 122
// eslint-disable-next-line @typescript-eslint/no-non-null-assertion
containerEle.value!.addEventListener(
'mouseup',
_upEvent => {
// eslint-disable-next-line @typescript-eslint/no-non-null-assertion
containerEle.value!.removeEventListener('mousemove', moveUpdate)
const stop = useEventListener(
containerEle,
'mousemove',
(moveEvent: MouseEvent) => {
stop()
moveUpdate(moveEvent)
},
{ once: true }
{
once: true
}
)
Copy link
Contributor

Choose a reason for hiding this comment

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

これが消えてる?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

あっ、ミスです直します

Comment on lines -28 to -29
const startEventName = isIOS() ? 'touchstart' : 'mousedown'
const endEventName = isIOS() ? 'touchend' : 'mouseup'
Copy link
Contributor

Choose a reason for hiding this comment

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

iOSで動作確認した方が良いかもね

@uni-kakurenbo uni-kakurenbo requested a review from cp-20 December 29, 2025 15:07
@uni-kakurenbo uni-kakurenbo changed the title optimize: 参照カウントと Effect Scope を用いてグローバルなイベント監視を効率化する optimize: VueUse を用いてグローバルなイベント監視を効率化する Dec 29, 2025
Copy link
Contributor

@cp-20 cp-20 left a comment

Choose a reason for hiding this comment

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

動作確認してないけど、動くならOKそう

return isObjectAndHasKey(plain, '$el') ? plain.$el : plain
return (
isObjectAndHasKey(plain, '$el') ? plain.$el : plain
) as UnrefElementReturn<T>
Copy link
Contributor

Choose a reason for hiding this comment

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

アサーションいらないんじゃない? (普通にアノテーションするだけで十分)

Copy link
Contributor Author

@uni-kakurenbo uni-kakurenbo Dec 29, 2025

Choose a reason for hiding this comment

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

その後 VueUse の unrefElement を利用するように書き換えたんですが、戻り値の型 (HTMLElement | SVGElement | undefined | null) がちょっと微妙だった (.$el の型を infer してほしかった) のでアサーションする形になってしまいました
https://github.com/traPtitech/traQ_S-UI/pull/4890/changes#diff-ad8f25153aa059247c28efc0e1a4b6aaae7d0020fea996985c41c9330ffa341a

Copy link
Contributor

Choose a reason for hiding this comment

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

微妙なのでアサーションするのは TypeScript の型安全性を破壊する行為なので非常に良くないです その型が気に食わないなら気に食わない部分を自分でハンドリングする必要があるはずです (型には意味があるはずなので)

Copy link
Contributor Author

Choose a reason for hiding this comment

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

色々試した結果結局このような形にすることしかできなかったのですが、この as any を外すことってできるんでしょうか....?(関数オーバーロードも実質的には型アサーションと変わりないですよね)

export function unrefElement<T>(
  element: MaybeRefOrGetter<T>
): T extends { $el: infer E } ? E : T {
  const plain = toValue(element)
  if (isObjectAndHasKey(plain, '$el')) return plain.$el as any
  return plain as any
}

Copy link
Contributor

Choose a reason for hiding this comment

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

最後の as any はいらないと思うけど、2行目のやつは外すの難しいかも

Copy link
Contributor Author

Choose a reason for hiding this comment

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

どっちを外しても Type *** is not assignable to type 'T extends { $el: infer E; } ? E : T' と言われてしまって困ってます

Copy link
Contributor

Choose a reason for hiding this comment

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

あ、ほんとだ 難しいな

Copy link
Contributor

Choose a reason for hiding this comment

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

as any するぐらいなら最初からアサーションした方がましだったかも すいません

Copy link
Contributor Author

Choose a reason for hiding this comment

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

やっぱり無理そうだったので諦めました :komata-nya:

@uni-kakurenbo uni-kakurenbo merged commit 57d6ef2 into master Dec 30, 2025
11 checks passed
@uni-kakurenbo uni-kakurenbo deleted the optimize/effect-scope branch December 30, 2025 01:39
@github-project-automation github-project-automation bot moved this from In progress to Done in traQ Client Dec 30, 2025
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

optimize performance optimization refactor

Projects

Status: Done

Development

Successfully merging this pull request may close these issues.

2 participants