こんにちは。弁護士ドットコム クラウドサイン事業本部 Product Engineering 部の林と申します。執筆時点では入社1か月の新入社員です。もちろん入社してはじめて書く技術ブログですが、新参者でも臆せず発信できる組織ということをアピールしつつ、ジョインしたての業務で学んだことを整理します。
Vue2.7へのアップグレードに伴うv-deep移行作業の背景
現在、クラウドサインのフロントエンドは Vue2 で実装されています。Vue2はサポート期限が近づいているのもあり、Vue3 へのバージョンアップが望まれます。ただ巨大なシステムを一気に Vue3 に移行するのは難易度が高いため、段階的移行のために Vue2.7 にする活動が進んでいます。
その中で私はv-deep
セレクタが使用されていたコンポーネントを Vue2.7 に対応させるタスクを担当しました。従来の::v-deep
が使えなくなるため、新たなdeepセレクター:deep()
に置き換える作業です。(deep セレクタの詳細はリンク先をご参照ください)
基本的には公式ドキュメントの示す例のとおり
.a ::v-deep .b { /* ... */ }
上記を
.a :deep(.b) { /* ... */ }
のように置き換えるという、そこまで難しくない作業になるはずでした。
v-deepを:deep()に移行する際に詰まったところ
作業を進める中で下記のようなコードがありました。
.hoge { & ::v-deep svg path, i { fill: #fff; } }
このセレクタをどう変換するか考えたとき、v-deep
はどのような範囲でセレクタに影響するか分からず、当初は下記のようにしました。
.hoge { & :deep(svg path, i) { fill: #fff; } }
しかし、これだと元のセレクタとは等価にはなりませんでした。
ブラウザの開発ツールで対象 DOM に当たっているセレクタを確認すると、元の& ::v-deep svg path, i {}
の方だと
.hoge[data-v-xxxxxxxx] svg path, .hoge i[data-v-xxxxxxxx]
ですが、& :deep(svg path,i) {}
とすると
.hoge[data-v-xxxxxxxx] svg path
となっており、i
に対するセレクタが消失してしまいました。
これはただ:deep()
の使用方法が違っていただけという話ですが、では::v-deep
や:deep()
はセレクタ結合に対してどのような範囲で適用されるのでしょうか。
正しい:deep()の適用範囲
結論、このように記述することで従来と等価なセレクタにすることができました。
.hoge { & :deep(svg path), i { fill: #fff; } }
ブラウザの開発者ツールで観測したセレクタはこちらです。
.hoge[data-v-xxxxxxxx] svg path, .hoge i[data-v-xxxxxxxx]
つまり、& ::v-deep svg path, i {}
というセレクタ指定だと、子孫結合子で結合されたセレクタには纏めて deep セレクタの影響がおよび、セレクターリストを跨いだ右辺のセレクタには影響を及ぼさないということです。
そのため、:deep(svg path)
とi
で分けることが正解であったということですね。
分解して表現するとこのようになります。
.hoge ::v-deep svg path {} .hoge i {}
こうすると、セレクターリストでsvg path
とi
は分かれていて、結合子によって結合されていたsvg path
のみにv-deep
が影響していたことが分かりやすいかなと思います。
ちなみに(GPT-4に聞いてみた)
正解は検証してみるまで分からなかったのですが、その前に流行りのGPT-4
とWeb Browsing
を使って回答を生成してみました。プロンプトは下記のような感じです。
あなたは最新のVue.jsの知見を持ったフロントエンドエンジニアです。以下のscssコードをVue3に合った形で`:deep()`を使う形で変換して下さい。 {変換前コード}
すると
.hoge { :deep(svg path), :deep(i) { fill: #fff; } }
と返してきました。確かに deep セレクタの影響がセレクターリストを跨ぐのであれば、こうなってもおかしくないですよね。
こちらのセレクタをブラウザの開発者ツールで観測するとこうなります。
.hoge[data-v-xxxxxxxx] svg path, .hoge[data-v-xxxxxxxx] i
割とおしいですよね。セレクターリストの両方に deep セレクタが適用されていることが分かります。
しかし元のセレクターはsvg path
にのみ deep セレクタが適用されておりi
に適用してはいけなかったため、等価なセレクタにはなりません。
※社外秘の情報はChatGPTには入力しないようにしています。
まとめ
業務を通じて Vue2 から Vue2.7 もしくは Vue3 にバージョンアップする際のv-deep
の扱いと影響範囲を知ることができました。
- deep セレクタを Vue3(Vue2.7)に移行する方法
- 新しい deep セレクター
:deep()
の使い方 - deep セレクタのセレクターリストに対する影響範囲
今後もプロダクトの Vue3 への完全なバージョンアップに貢献していきたいと考えています。