Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Custom events should not be permeable #6086

Closed
Linkontoask opened this issue Jun 10, 2022 · 13 comments
Closed

Custom events should not be permeable #6086

Linkontoask opened this issue Jun 10, 2022 · 13 comments

Comments

@Linkontoask
Copy link
Author

Additional scenario: When I use component components, I often register events that are not generic, but may listen for unintended actions

@lidlanca
Copy link
Contributor

options 1

defineEmit on the "immediate" component (Comp). so vue does not attach a native event listener.

options 2

guard native event in the consumer level, (in case you don't have control over Comp)

function onChange(event) {
  if(event instanceof Event ) return 
  title.value = e.target.checked
}

@KaelWD
Copy link
Contributor

KaelWD commented Jun 10, 2022

@Linkontoask
Copy link
Author

Linkontoask commented Jun 10, 2022

The first sense is that the custom event is only applied to the current component and not triggered by the grandchild component due to the failure to declare defineEmit

<Comp @change="onChange" />

The change event should only be triggered by Comp emit('change')

This doesn't match the first intuition, you guys are talking about a user-side solution, what I'm thinking is why would vue do that?

@lidlanca
Copy link
Contributor

I jumped to the workarounds to save you some time,

you can check the docs to better understand what is expected from vue when you bind events to a component with a defined emit and without,
and what is the difference between native event, and vue emitted "events".

if you are trying to push a new feature or change of spec, I wish you good luck.

@Linkontoask
Copy link
Author

Linkontoask commented Jun 11, 2022

Thank you for your replies. @lidlanca @KaelWD

I'm here to talk about an application scenario

<component :is="hit" @change="onChange" />

const hit = Comp1 || Comp2 || Comp3

It may be that Comp2 does not need to respond to this event, but it happens that there are elements in Comp2 that do respond to the change event.

The user will find an unexpected response when handling onChange and will have to spend time to find the problem.

@LinusBorg
Copy link
Member

I agree that this specific scenario is an easy pitfall to introduce a bug.

However it's documented behavior that we could only change in a major release, as far as I can see right now. Though I'd be interested in suggestions

For now, what we can do is to better document this pitfall in the docs about <component>, so people are aware that they need to i.e. use a computed property to dynamically create an object with the right props and event listeners depending on the current component used in :is=.

We could also consider an eslint rule maybe?

@Linkontoask
Copy link
Author

Thank you for your answer. @LinusBorg

I think it could be described clearly in the <component> documentation that props and events should be calculated dynamically based on :is and not set in stone.

If you can add eslint rules that would be even better.

@yyx990803
Copy link
Member

In Vue 2, custom vs. native event listeners are separated via the .native modifier.

In Vue 3:

  1. Listeners will capture both custom and native listeners if no emits or defineEmits are explicitly declared
  2. A listener will only capture custom events if it's declared as custom only via emits

Given that this is documented behavior, we cannot change how it works. It also means that when you attach an event listener to a component, you should not make the assumption that the event is only triggered by component custom events.

For the case discussed here - I think it's quite rare to attach an event listener on a dynamic component where not all possible components actually emit that event. When it happens, however, it could indeed be a pitfall. I'm not quite sure how Vue can change its behavior to avoid this without causing breaking changes.

@lidlanca
Copy link
Contributor

I'm not quite sure how Vue can change its behavior to avoid this without causing breaking changes.

we can introduce modifiers to vue 3 (prefix).

The modifier can configure the type of binding ( native / emit ).
additionally we can also introduce case sensitive modifier, that can solve
#5401 to escape the normalization and use event name as-is

to demonstrate the idea, we can look for a prefix that minimize possibility of breaking existing code:

  <!-- auto -->
  <div @Click=handler>1</div>
  
  <!-- auto + case sensitive -->
  <div @\Click=handler>2</div>
  
  <!-- emit only -->
  <div @@Click=handler>3</div>
  
  <!-- emit only + case sensitive -->
  <div @@\Click=handler>4</div>
  
  <!-- native only -->
  <div @^Click=handler>5</div>
  
  <!-- native + case sensitive -->
  <div @^\Click=handler>6</div>

@iwusong
Copy link
Contributor

iwusong commented Jun 14, 2022

Thank you for your replies. @lidlanca @KaelWD

I'm here to talk about an application scenario

<component :is="hit" @change="onChange" />

const hit = Comp1 || Comp2 || Comp3

It may be that Comp2 does not need to respond to this event, but it happens that there are elements in Comp2 that do respond to the change event.

The user will find an unexpected response when handling onChange and will have to spend time to find the problem.

add emits to Comp2 if does not need to respond to this event.
will there be some problems?

@LinusBorg
Copy link
Member

@lidlanca Adding more modifiers to covers these cases would be thinkable in theory, though I'd be hesitant to add more shorthands as it will make the template more and more cryptic.

This should likely be discussed in an RFC: github.com/vuejs/rfcs

@lidlanca
Copy link
Contributor

I actually started a discussion in RFC

vuejs/rfcs#451

@github-actions github-actions bot locked and limited conversation to collaborators Sep 25, 2023
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
None yet
Projects
None yet
Development

No branches or pull requests

6 participants