Description
Creating an issue out of this ⬇ hoping for more discussion!
Discussed in #433
Originally posted by athewsey February 25, 2022
I recently came across vuejs/vue#12433 because I have a use case for this feature too - and saw that the original requester was asked to bring it here to the RFCs process but couldn't find any such issue/PR/discussion yet.
Essentially, I'm using Vue to build some Custom Elements / native web components which emit events. As noted in the 'Events' section of the Vue Web Components doc:
Events emitted via
this.$emit
or setupemit
are dispatched as native CustomEvents on the custom element. Additional event arguments (payload) will be exposed as an array on the CustomEvent object as itsdetails
property.
The challenge here is that, because params are fed directly through to options.detail
on the CustomEvent constructor, I don't see any way to set other Event options - particularly bubbles
and cancelable
.
These are important features for native/DOM event handling, and it seems to me like it's not sufficient to just assume one setting always holds because presumably developers using this feature are doing so because (like me) their architecture is not vanilla "Vue-all-the-way-down".
It seems possible to work around my specific bubbling requirement by manually raising a CustomEvent and setting composed true
, to allow it to bubble out of the shadow root and up through parents:
<!-- MyCoolComponent.ce.vue -->
<script setup lang="ts">
import { ref } from "vue"
const props = defineProps<{ val: number }>();
const thisEl = ref<HTMLElement>();
const emit = defineEmits<{
(e: "foobar", val: number): void;
}>();
function onClickRemove() {
// No way to set bubbling via this VueJS option:
// emit("foobar", props.val);
// Can set bubbling via native, but extra complexity:
thisEl.value.dispatchEvent(
new CustomEvent(
"foobar",
{
detail: [props.val],
bubbles: true,
composed: true,
}
)
);
}
</script>
<template>
<p @click="onClick();">Click me</p>
</template>
...But I don't see how it can be done today without the composed
option (which I guess could be a problem for users with multiple nested shadow roots in their page?).
I'm new to Vue's codebase and RFC process, but hopefully we can find a way to support this extra configuration that's still consistent-enough with what users are familiar with in normal Vue $emit
?
Activity