Per the Vue docs, it's possible to build components in Vue (v3) and package them as native Web Components for use with any framework or none at all.
As I've already found, the gap between design models for Vue components and Web Components can make this complex and sometimes a straight-up bad idea (at what point is it better and more maintainable to just go ahead building fully-native components?)... But let's assume for a moment that it's necessary here.
My question - What's the best way to expose a function-like interface on a Vue-built Web Component (to parent nodes)?
The Vue doc discusses passing in reactive data via props/slots, and publishing CustomEvents from the components, but I don't see mention of taking function calls (or at a stretch, events) from outside. As far as I can tell this is a pretty strong assumption that data and event flow on the rest of the app/page works in a very "Vue-like way"?
For now, my workaround on this is to look up the host element in onMounted()
(as per this question) and just set whatever extra properties are required at that point (hoping they shouldn't be required before the Vue component mounts, because I'm not aware of any external events raised when Vue finishes mounting the custom element).
This way the function can still be defined in the context of, and access variables/etc from, the setup function - but can be called by other elements on the page that only have a reference to the element, not the Vue component.
Can't say I like it much though:
<template>
<div ref="someElInTemplate">...</div>
</template>
<script lang="ts">
interface MyCoolHTMLElement extends HTMLElement {
myCoolFunction: () => void;
}
</script>
<script setup lang="ts">
const someElInTemplate = ref<HTMLElement>();
function myCoolFunction() { }
onMounted(() => {
const hostNode = (
somElInTemplate.value?.getRootNode() as ShadowRoot | undefined
)?.host as MyCoolHTMLElement;
hostNode.myCoolFunction = myCoolFunction;
});
</script>