Vuetify2のv-iconって一体どうやって動いてるのよ!!!
こんにちは、Vueに触れて1年以上経過するもVueの仕組みを何一つ理解していない自信があるとれいすです。
記事名の通り、v-iconってどういう仕組みで動いているのかを知りたくなったため、せっかくなら記事にしてみようと思った次第です。
というのも
v-iconの使いかた
<v-icon>mdi-XXXX</v-icon>
って書いてアイコンになるのは不思議だなーと、無知ワイは思ったわけです。
それでは早速見ていきましょー
この記事はVuetify 2をターゲットにした記事です。
Vuetify 3では中身が違うので、「Vuetify 3の記事じゃないじゃん」とか言われても困ります。
ソースコードを見る
ソースコードを覗いてみましょう。
なお、気になったところだけ抜粋します。
VIcon.ts
getIcon() {
let iconName = '';
if (this.$slots.default) iconName = this.$slots.default[0].text.trim();
return remapInternalIcon(this, iconName);
}
// 中略 //
render (h: CreateElement): VNode {
const icon = this.getIcon()
if (typeof icon === 'string') {
if (isSvgPath(icon)) {
return this.renderSvgIcon(icon, h)
}
return this.renderFontIcon(icon, h)
}
return this.renderSvgIconComponent(icon, h)
}
this.getIcon()
でアイコンの名前であるmdi-XXXX
をthis.$slots.default
から引っ張ってきて、アイコンの名前と一緒にヘルパー関数のremapInternalIcon()
に飛んでいます。
その中身が↓
helpers.ts
function remapInternalIcon (vm: Vue, iconName: string): VuetifyIcon {
// Look for custom component in the configuration
const component = vm.$vuetify.icons.component
// Look for overrides
if (iconName.startsWith('$')) {
// Get the target icon name
const iconPath = `$vuetify.icons.values.${iconName.split('$').pop()!.split('.').pop()}`
// Now look up icon indirection name,
// e.g. '$vuetify.icons.values.cancel'
const override = getObjectValueByPath(vm, iconPath, iconName)
if (typeof override === 'string') iconName = override
else return override
}
if (component == null) {
return iconName
}
return {
component,
props: {
icon: iconName,
},
}
}
remapInternalIcon()
は$cancel
や$vuetify.icons.cancel
のような内部名を、そのアイコンの正しい?名前、またはコンポーネントにリマップしてくれるものだそうです。
結論
`slot`を使って指定されたアイコンの名前を取得し、一意に定まるアイコンを取得してレンダリングしている
という理解に落ち着きました。違ったらコメントでご指摘ください。
ではまた。