TL;DR
- カスタム要素とVueコンポーネントの区別がつくようにコンフィグに設定をする必要がある。
- カスタムイベントの購読はrefつけてaddEventListenerする必要がある。
- 名前付きスロットは使えない。
はじめに
業務でCustomElementsを使ったUIコンポーネントライブラリを作成し、それをVue.js上で使う機会がありました。
その際、Vueの都合上?使えない機能やいまいちなところがあったのでメモとして残します。
VueはCustomElementsとVueコンポーネントの区別がつかない
カスタム要素をVueテンプレート上に記述すると、Vueはその名前のVueコンポーネントを探しに行き、もちろん存在しないので、warnログを出力してしまいます。
これを回避するために、カスタム要素のタグ名プレフィックスとVueコンポーネントのプレフィックスを明確に分け、以下の設定でVueがカスタム要素をVueコンポーネントと認識させないようにする必要があります。
Vue2.x
import Vue from "vue"
Vue.config.ignoredElements = [
/^custom-/
]
Vue3.x
import { createApp } from "vue"
import App from "path/to/your/app.vue"
const app = createApp(App)
app.config.isCustomElement = tag => tag.startsWith("custom-")
カスタムイベントの購読
カスタム要素からdispatchEvent(new CustomEvent(..))している場合、テンプレート上での@{イベント名}による購読ではなく、refからaddEventListenerする必要があります。
これは動かない
<custom-element @custom-event="doSomething"></custom-element>
これは動く
<template>
<custom-element ref="myElement"></custom-element>
</template>
<script>
export default {
mounted() {
this.$refs.myElement.addEventListener("custom-event", this.doSomething)
}
}
</script>
カスタム要素の名前付きスロットは使えない
カスタム要素で名前付きスロットを使う場合slot="name"と属性を指定する必要があるのですが、
これがVueの古い記法と被っていて、Vueテンプレート上に記載するとdeprecatedの警告がでます。※Linter使っている場合
これを回避しても、Vueはslot属性をRealDOMに書き込まないようで、カスタム要素側では名前付きスロットを受け取れません。
※回避方法知っている方いたら教えてください。
※カスタム要素のデフォルトスロットは問題なく利用できます。
おわりに
ちゃんと確認したつもりですが、間違っているところがあったら教えていただけるとありがたいです。