同じURIのリンクなのに aria-current
の属性がつく場合とつかない場合があって結構悩んだのでそのメモ。
どのような問題が発生していたのか?
よくあるページネーションの実装で、1ページ目の/hoge?page=1
はクエリを削除してリンクを表示していた。
ページ番号を削除したNuxtLinkにおいて aria-current
の属性がつく場合とつかない場合があって謎の挙動をしていた…。
ページクエリを削除するために以下のような処理をしてNuxtLinkの to属性に渡している
1
2
3
4
5
6
7
8
9
10
11
|
if (page == 1) {
const nextQuery = Object.assign({}, this.route.query, {
[this.pageQueryName]: undefined
})
}
return {
path: this.route.path,
params: this.route.params,
query: nextQuery ? nextQuery : this.router.query
}
|
そもそもNuxtLinkはほぼRouterLink
NuxtLinkは独自のコンポーネントのかと思ったら、vue-routerのRouterLinkを継承していた。
そもそも aria-current
の出し分けはRouterLinkの方の処理だった。
aria-currentを表示するかしないかのコードについて
該当箇所が以下の通り。
1
2
3
4
5
6
|
classes[exactActiveClass] = isSameRoute(current, compareTarget, this.exactPath);
classes[activeClass] = this.exact || this.exactPath
? classes[exactActiveClass]
: isIncludedRoute(current, compareTarget);
var ariaCurrentValue = classes[exactActiveClass] ? this.ariaCurrentValue : null;
|
ここではvar ariaCurrentValue
がaria-currentに入る中身になっていて、this.ariaCurrentValue
はデフォルト値になっている。
つまり、isSameRouteの関数の判定によって変わってくる。
isSameRouteの関数について
該当コードは以下の通り
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
|
function isSameRoute (a, b, onlyPath) {
if (b === START) {
return a === b
} else if (!b) {
return false
} else if (a.path && b.path) {
return a.path.replace(trailingSlashRE, '') === b.path.replace(trailingSlashRE, '') && (onlyPath ||
a.hash === b.hash &&
isObjectEqual(a.query, b.query))
} else if (a.name && b.name) {
return (
a.name === b.name &&
(onlyPath || (
a.hash === b.hash &&
isObjectEqual(a.query, b.query) &&
isObjectEqual(a.params, b.params))
)
)
} else {
return false
}
}
|
単純なfullPathを使った判定をしているのかと、pathが一緒の場合はQueryの通り。
何が問題だったのか?
問題はページクエリの削除のしかたに問題があった。
1
|
query = { page: undefined }
|
とすると最終的に生成されるURLとしては page
クエリが削除された状態で生成される。
しかし isSameRoute
では queryパラメータも完全に同一かどうかチェックしていた。
そのため、 同じ /hoge
URLにアクセスした場合でも、queryパラメータをundefinedを使って削除しているNuxtLinkの場合は isSameRoute
が falseになり aria-current
の属性が付与されなかった。
つまり以下の書き方のように直せば意図通りに isSameRoute
の判定がされた。
1
2
3
4
5
6
7
8
9
10
|
if (page == 1) {
const { page, ...queryParameters } = this.route.query
const nextQuery = Object.assign({}, queryParameters)
}
return {
path: this.route.path,
params: this.route.params,
query: nextQuery ? nextQuery : this.router.query
}
|
参考
Vue Routerでquery書き換えができなかった(凡ミス)