A.
さらに Composables でラップして使いやすくしてしまおう
Motivation
- Nuxt3 でクエリパラメータから値を取り出すときの配列処理が面倒だった
- useRoute() と同様の操作感で、欲しいものを取り出す処理が欲しかった
- 取り出す過程で、特定のクエリパラメータへの操作を追加したかった(今回はピリオド区切りで分割して返却する)
→ それなら、 composables で定義して使おう!
※こんなことを実現したい
Requirements
- "nuxt": "^3.13.2",
- "vue": "^3.4.21",
- "vue-router": "^4.3.0",
Snippets
① composables 定義側
Composables ディレクトリを使って useXXX として処理を記述
const defaultDelimiter = "."
export const useQueryParam = (key: string, delimiter = defaultDelimiter): string[] => {
const { query } = useRoute()
if (query[key] instanceof Array) {
return query[key].flatMap((v) => v?.split(delimiter) ?? [])
}
else {
return query[key]?.split(delimiter) ?? []
}
}
② 利用側
利用側で実行していたコードをcomposablesに持っていっただけです。特別代わり映えはしませんがBefore,Afterを載せておきます。
function getParam1Before() {
const { query } = useRoute();
if (query.param1 instanceof Array) {
return query.param1.flatMap(
(p: LocationQueryValue) => p?.split(".") ?? []
);
} else {
return query.param1?.split(".") ?? [];
}
}
function getParam1After() {
return useQueryParam("param1");
}
Result
以下のようにクエリパラメータが指定されたとき、思ったようにパースできました
パターン | パラメータ | 返却値 |
---|---|---|
指定なし | none | [] |
1個指定 | param1=apple | ["apple"] |
2個指定 | param1=apple¶m1=orange | ["apple", "orange"] |
デリミタ付 | param1=apple.orange¶m1=lemon | ["apple", "orange", "lemon"] |
Opinion
#1
composables 自体は、状態を持ったオブジェクトを包みこんで使いやすい機能を提供するもの、と捉えていました。
それ自体が state を持たない composables を作ることには少し抵抗がありましたが、 use〇〇
をラップして使い勝手のよい use〇〇
を新設するのは、そんなに悪くない手法と感じました。
これまでは面倒くさいが勝ってしまって、「同一のクエリパラメータを複数指定したリクエストは捨てる」ような ADR を設けて、配列の1個目しか取らないようなコードを書いたこともありますが、そこまでしなくても良かったのかもしれません。
#2
展望としては、今回のコードは追加のオプションとしてデリミタを渡すようなものを用意しましたが、 LocationQueryValue
型から何かしらの他のドメインモデル配列を生成する関数を渡すように作り変えるとより汎用性は上がるかもしれませんね。
#3
頭で貼付したキャプチャに補足すると、「くさ・どくの複合、みずのみ、をそれぞれ並べたい」ケースもあるかもしれませんが、今回は考慮外です。ただパラメータに列挙させるようなケースで、万が一パラメータの指定をミスした場合へのケアを考えるような文脈と捉えてくださいませ。
#4
composables とは何なのか、まだ理解できていない部分もあるので、ご指導ご鞭撻、そのほかのユースケースなどございましたら、是非コメントへ!