Vue を業務で使い始めました。ちゃんと理解できていないところがあるので公式ドキュメントを読み直して勉強になったことを書き残しておく。
算出プロパティ (computed)
computed と watch のどちらを使うべきか悩むことが多かったが、公式ドキュメントにベストプラクティスが書いてあった。
- getter 関数は計算のみを行い、副作用がないようにする
- getter の内部で他のステートを変更しない
- 非同期リクエストを実行しない
- DOM を変更したりしない
計算結果は読み取り専用として扱い、変更するなということらしい。computed では、値を計算して返すことだけ行う。
reverse()
と sort()
のような元の配列を変更するようなメソッド (ミューテーションメソッド) は、computed の副作用がないようにするという原則に違反してしまう。ミューテーションメソッドを使いたければ、元の配列のコピーを作成する。
- return numbers.reverse()
+ return [...numbers].reverse()
v-for
特別な理由がない限り、key
属性を必ず指定する。参考
- コンポーネントを再描画できる
- 当然再描画にはコストがかかるので、パフォーマンスが低下することがある。ステートレスな単純な要素の繰り返しであれば避ける。
- 一意なものにする
ウォッチャー (watch)
computed と異なり、状態の変更に応じて副作用を伴う処理を実行する時に使う。リアクティブな状態の一部 (ref) が変更されるたびにコールバックを実行する
- 非同期処理 (API 呼び出し) を行う
- 取得したデータでリアクティブなデータを更新する
- wathch ではデータを返さない (return しない)
- 更新前と更新後の値が使える
パスカルケース、キャメルケース、ケバブケースのどちらを使うか
コンポーネントのタグには、可能な限り PascalCase を用いる。参考
// 推奨 (テンプレートの可読性が高まるため)
<MyComponent>
// ケバブケースでも書ける (非推奨)
<my-component>
props 名はキャメルケースを用いる。
defineProps({
greetingMessage: String
})
子コンポーネントに props を渡すときには、常に kebab-case(ケバブケース)を用いて HTML の属性に揃えるのが慣例となっているらしい。参考
<MyComponent greeting-message="hello" />
emit でも同じらしい
// emit 名はキャメルケース
<button @click="$emit('someEvent')">Click Me</button>
// 親側はケバブケースを使って購読する
<MyComponent @some-event.once="callback" />
props
親のプロパティが更新されたときには子にも流れるが、その逆はない。親コンポーネントが更新されるたびに、子コンポーネント内のすべての props は最新の値に更新される。子コンポーネント内で props の変更をしてはいけない。(v-bind)
また子コンポーネントは、受け取った props のうち少なくとも 1 つが変更された更新する。
一方向バインディングと呼ぶらしい。参考
v-model
双方向バインディングを実現する。defineModel()
が返す値は ref なのでリアクティブな値になる。
inputを含むコンポーネントを作成する場合、今までは引数を定義するための props と、親コンポーネントへ値を受け渡す関数を定義するための emits、どちらも記述する必要があった。