はじめに
最近Custom ElementsからイベントをDOMに伝えて処理を行うのをやったのですが、仕組みについて理解するのに時間がかかってしまったので、備忘録としてやり方をまとめます
今回は以下のリポジトリを利用してHelloボタン
をクリックしたら親で検知してコンソールでHello
を表示してみます
準備
$ git clone git@github.com:jinwatanabe/react-web-component-sample.git
$ cd react-web-component-sample
$ yarn dev
localhost:5173
を開くと以下の画面が表示されます
Custom Elementsでイベント発火する
まずはCustom Elementsでイベントを発火したことを親(DOM)に伝える処理を追加していきます
ここでは、emitMessage
というイベントを親に伝えます
まずはsrc/index.tsx
をひらいて、SampleElement
にたいしてイベント発火の関数を渡せるようにします
connectedCallback() {
this.root.render(
<CacheProvider value={this.cache}>
<SampleElement
onEventExecution={(message: string) => {
this.dispatchEvent(
new CustomEvent("emitMessage", { detail: { message } })
);
}}
/>
</CacheProvider>
);
}
dispatchEvent
でイベント発火が行われます
customEvent
でイベント名
とdetailP
プロパティを使用してカスタムデータを渡すことができます
この設定をすることでWebComponentsを利用している側(ここではindex.html)でイベント(emitMessage)を検知できるようになります
次に、実際に関数を呼び出す部分を実装します。
ここではHelloボタン
を用意してクリックしたタイミングで先程渡したイベント発火関数を実行します
const SampleElement: FC<{
onEventExecution: (message: string) => void;
}> = ({ onEventExecution }) => {
const sendHello = () => {
onEventExecution("Hello");
};
return (
<>
<h1
css={css`
color: red;
`}
>
Hello, world!
</h1>
<ul>
<li>test</li>
</ul>
<a href="#">link</a>
<button onClick={() => sendHello()}>Hello</button>
</>
);
};
これでCustom Elementsの準備は整いました
WebComponentsを利用する側でイベントを検知できるようにする
/index.html
を以下のように修正します
<body>
<script src="./src/index.tsx" type="module"></script>
<div>
<sample-element></sample-element>
</div>
<script>
const emitMessage = (event) => {
const message = event.detail.message;
console.log(message);
};
const sampleElement = document.querySelector("sample-element");
sampleElement.addEventListener("emitMessage", emitMessage);
</script>
</body>
script
を追加しました
sample-element
に対してイベントリスナー(emitMessage)を追加しました
イベントが発火したらコンソールでmessageを表示します
これで準備ができたので、HelloボタンをクリックするとコンソールにHello
と表示されます
おわりに
Custom Elementsでの関数名とindex.htmlのイベント名を一緒にしていたので少し迷いましたが、理解するとかなりシンプルに使えるなと感じました
参考