From 81d98949b385647bda73b9cfb44a8c66e2fff5f8 Mon Sep 17 00:00:00 2001 From: Waldemar Lehner Date: Tue, 23 Apr 2024 11:27:39 +0200 Subject: [PATCH] feat: Implement Vue Web Component, add nested Vue Web Component into Vanilla TS app --- webcomponent-react/src/main.tsx | 1 - webcomponent-vanilla/src/Frontend.ts | 36 ++++++++++++++++++ webcomponent-vanilla/src/index.module.scss | 4 ++ webcomponent-vue/src/App.vue | 2 +- .../src/components/Frontend.ce.vue | 1 + webcomponent-vue/src/webcomponent.ts | 38 +++++++------------ webcomponent-vue/vite-webcomponent.config.ts | 2 - 7 files changed, 56 insertions(+), 28 deletions(-) diff --git a/webcomponent-react/src/main.tsx b/webcomponent-react/src/main.tsx index 3d7150d..e63eef4 100644 --- a/webcomponent-react/src/main.tsx +++ b/webcomponent-react/src/main.tsx @@ -1,7 +1,6 @@ import React from 'react' import ReactDOM from 'react-dom/client' import App from './App.tsx' -import './index.css' ReactDOM.createRoot(document.getElementById('root')!).render( diff --git a/webcomponent-vanilla/src/Frontend.ts b/webcomponent-vanilla/src/Frontend.ts index 064339e..b6de886 100644 --- a/webcomponent-vanilla/src/Frontend.ts +++ b/webcomponent-vanilla/src/Frontend.ts @@ -19,9 +19,16 @@ const template = `

Diese Komponent ist mit Vanilla TS / Vite implementiert

+ +

Als Demonstration, dass Verschachtelung auch möglich ist, wurde hier die Vite+Vue3 Komponente verschachtelt einbunden und an den lokalen Zustand angebunden

+ +
Loading...
+ ` + + export default function createFrontend(parent: HTMLElement, initialCount: number, setCount: (count: number) => void) { parent.innerHTML = template @@ -30,6 +37,7 @@ export default function createFrontend(parent: HTMLElement, initialCount: number const counterElement = parent.querySelector("#counter")! const localCounterElement = parent.querySelector("#local-counter")! + let nestedFrontendElement: Element | undefined = undefined const updateCounter = (newCount: number) => { count = newCount @@ -39,6 +47,12 @@ export default function createFrontend(parent: HTMLElement, initialCount: number const updateLocalCounter = (newCount: number) => { localCount = newCount localCounterElement.innerHTML = `Lokaler Zustand ${newCount}` + + if(!!nestedFrontendElement) { + // @ts-ignore + nestedFrontendElement.count = localCount + } + } counterElement.addEventListener("click", () => setCount(count + 1)) @@ -47,5 +61,27 @@ export default function createFrontend(parent: HTMLElement, initialCount: number updateCounter(count) updateLocalCounter(localCount) + const nestedFrontendRoot = parent.querySelector("#nested-frontend")! + + insertNestedFrontend(nestedFrontendRoot, updateLocalCounter).then( e => nestedFrontendElement = e ) + return updateCounter } + +async function insertNestedFrontend(element: HTMLDivElement, newStateCallback: (count: number) => void) { + // @ts-ignore + (await import("http://localhost:5002/webcomponent.js")).default("webcomponent-vue") // redundant, but here anyways + // for consistency + + element.innerHTML = `` + + const nestedFrontend = element.querySelector("webcomponent-vue")! + + + nestedFrontend.addEventListener("count", (ev) => { + const [count] = (ev as any).detail as [number] + newStateCallback(count) + }) + + return nestedFrontend +} diff --git a/webcomponent-vanilla/src/index.module.scss b/webcomponent-vanilla/src/index.module.scss index 16d1ccc..bbd425f 100644 --- a/webcomponent-vanilla/src/index.module.scss +++ b/webcomponent-vanilla/src/index.module.scss @@ -72,3 +72,7 @@ } } +.nested { + border: wheat 1px solid; + display: flow-root; +} diff --git a/webcomponent-vue/src/App.vue b/webcomponent-vue/src/App.vue index ae14100..5552dd4 100644 --- a/webcomponent-vue/src/App.vue +++ b/webcomponent-vue/src/App.vue @@ -1,6 +1,6 @@