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

"Extraneous non-props attributes passed" warning posted for v-on attribute #1001

Closed
mika76 opened this issue Apr 20, 2020 · 4 comments
Closed
Labels
good first issue Good for newcomers ✨ feature request New feature or request

Comments

@mika76
Copy link

mika76 commented Apr 20, 2020

Version

3.0.0-beta.2

Reproduction link

https://jsfiddle.net/dajb4q2k/1/

Steps to reproduce

  • Create a child component with a fragment which emits some event
  • Add a v-on event handler in the parent

What is expected?

The event should be thrown and no warning needs to be given

What is actually happening?

The even works perfectly fine, but a warning is thrown:

vue.global.js:4683 [Vue warn]: Extraneous non-props attributes (onBtn-clicked) were passed to component but could not be automatically inherited because component renders fragment or text root nodes. 
  at <Anonymous onBtn-clicked=fn<cl> >  
  at <Anonymous> (Root)

I think the warning should not be thrown for v-on attributes

@aztalbot
Copy link
Contributor

aztalbot commented Apr 20, 2020

I wonder if the intended way to resolve that warning would be for the parent component of the fragment to declare "btn-clicked" in emits or to do v-bind="$attrs" on one of the children. It prevents the warning because it parses it out of attrs. So maybe the error should be improved to direct the user to either add the event to emits or do v-bind="$attrs"?

I think there are cases where a user might attach a listener and not understand why it doesn't pass down to the fragment, so it might be better to provide emits directions in the warning instead of not having a warning.


Although if the parent of the fragments were a Function component, I'm not sure that there is a way to do that. Maybe don't warn about extraneous v-on props on Function components, and warn on stateful components that the event should be added to emits?

For Function components you can also use emits to prevent the warning. or do child.props = ['onBtnClicked'] to prevent that warning, so the warning could direct the user to do that if the event attr isn't parsed out. One caveat here is that now there is a sort of misalignment in non-DOM templates, since both @btn-clicked and @btnClicked will be parsed out in the prop (no warning), but only btn-clicked will be emitted (events are case-sensitive). Sorry for all the crossed out stuff, still getting used to Vue 3.

The problem with not warning at all is I think it's easy for someone to add, say, a click event to that parent of the fragments and expect it to work. So I think directing the user to declare an event or prop might be better.


Code-wise, it seems like in dev there may need to be logic for functional components similar to that of stateful components, which checks for usage of $attrs or accessing setupContext.attrs and calls markAttrsAccessed. That could mean effectively silencing the warning for optional-prop function components, since I guess the warning would no longer makes sense (all attrs would be props).

@mika76 mika76 changed the title "Extraneous non-props attributes passsed" warning posted for v-on attribute "Extraneous non-props attributes passed" warning posted for v-on attribute Apr 20, 2020
@yyx990803
Copy link
Member

@aztalbot yes, in this case the warning should nudge the user to add the emitted event to the emits option.

@Awolwe
Copy link

Awolwe commented Apr 1, 2021

onclick="void(0);" to App.vue helped to me

@DevLucem
Copy link

DevLucem commented Aug 22, 2021

If you are using a custom component that takes in v-model you need to add the name of your component as a class name in the root element.

Example

<template>
  <div class="Selector m-2">
    <label class="subtitle" :for="title">{{title}}</label>
    <select class="m-2 px-4 bg-transparent border border-green-700 rounded" aria-label="none" name="Select" :id="title" ref="select" @input="selected()">
      <option v-for="option in options" :key="option" value="option">{{option}}</option>
    </select>
  </div>
</template>

<script>
export default {
  name: "Selector",
  props: ['title', 'options', 'value'],
  methods: {
    selected(){
      this.$emit('input', {value: +this.$refs.select.value})
    }
  }
}
</script>

Then you can call it like
<Selector title="Project" :options="['A', 'B']" v-model="project"/>

@github-actions github-actions bot locked and limited conversation to collaborators Oct 13, 2023
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
good first issue Good for newcomers ✨ feature request New feature or request
Projects
None yet
Development

No branches or pull requests

5 participants