0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 3 years have passed since last update.

CustomElementsをVueで使う際の注意

Last updated at Posted at 2021-02-18

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に書き込まないようで、カスタム要素側では名前付きスロットを受け取れません。
※回避方法知っている方いたら教えてください。
※カスタム要素のデフォルトスロットは問題なく利用できます。

おわりに

ちゃんと確認したつもりですが、間違っているところがあったら教えていただけるとありがたいです。

0
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?