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

vue/require-explicit-emits not picking up listed emits in different cases #1347

Closed
2 tasks done
jameschenjav opened this issue Oct 28, 2020 · 7 comments · Fixed by #1364
Closed
2 tasks done

vue/require-explicit-emits not picking up listed emits in different cases #1347

jameschenjav opened this issue Oct 28, 2020 · 7 comments · Fixed by #1364

Comments

@jameschenjav
Copy link

jameschenjav commented Oct 28, 2020

Checklist

  • I have tried restarting my IDE and the issue persists.
  • I have read the FAQ and my problem is not listed.

Tell us about your environment

  • ESLint version: 7.11.0
  • eslint-plugin-vue version: 7.1.0
  • Node version: 12.18.4
  • Operating System: macOS 10.15.7

Please show your full configuration:

module.exports = {
  root: true,
  env: {
    node: true,
  },
  extends: [
    'plugin:vue/vue3-recommended',
    '@vue/airbnb',
    '@vue/typescript/recommended',
  ],
  parserOptions: {
    ecmaVersion: 2020,
  },
  rules: {
    'no-console': process.env.NODE_ENV === 'production' ? 'warn' : 'off',
    'no-debugger': process.env.NODE_ENV === 'production' ? 'warn' : 'off',
  },
};

What did you do?

<template>
  <h1>Vue3 Fragment</h1>
  <div @click="$emit('foo-bar')">
    FooBar
  </div>
  <code>
    runtime-core.esm-bundler.js?5c40:38 [Vue warn]:
    Extraneous non-emits event listeners (fooBar) were passed to component but could not
    be automatically inherited because component renders fragment or text root nodes.
    If the listener is intended to be a component custom event listener only, declare it
    using the "emits" option.
  </code>
</template>

<script lang="ts">
import { defineComponent } from 'vue';

export default defineComponent({
  name: 'FooBar',
  emits: ['fooBar'],
});
</script>

What did you expect to happen?
No lint warning or error in this case.

If I changed it to emits: ['foo-bar'], I would get a warning message in browsers console:

[Vue warn]: Extraneous non-emits event listeners (fooBar) were passed to component but could not be automatically inherited because component renders fragment or text root nodes. If the listener is intended to be a component custom event listener only, declare it using the "emits" option. 
  at <FooBar onFooBar=fn<onFooBar> > 
  at <App>

What actually happened?

yarn run v1.22.10
$ vue-cli-service lint
warning: The "foo-bar" event has been triggered but not declared on `emits` option (vue/require-explicit-emits) at src/components/FooBar.vue:3:22:
  1 | <template>
  2 |   <h1>This is Fragment</h1>
> 3 |   <div @click="$emit('foo-bar')">
    |                      ^
  4 |     FooBar
  5 |   </div>
  6 |   <code>

Repository to reproduce this issue

https://github.com/jameschenjav/eslint-plugin-vue-147

@jameschenjav
Copy link
Author

I am not sure it's a bug. I guess it will be harder to change Vue3 runtime than the plugin?
Now I have to emits both cases in my fragment components which is hideous.

@ota-meshi
Copy link
Member

ota-meshi commented Oct 29, 2020

Hmm... I started looking into this, but if I don't match the cases, the Type check will probably result in an error.

  emits: ["fooBar"],
  methods: {
    handleClick() {
      this.$emit("foo-bar") // <- Argument of type '"foo-bar"' is not assignable to parameter of type '"fooBar"'.
    }
  }

@ota-meshi
Copy link
Member

The documentation says that events emitted by camelCase cannot be listened to by kebab-case v-on, but it may actually work.

https://v3.vuejs.org/guide/component-custom-events.html#event-names

If this behavior is what Vue intended, the following source code may be correct.

<template>
  <h1>Vue3 Fragment</h1>
  <div @click="$emit('fooBar')">
    FooBar
  </div>
</template>

<script lang="ts">
import { defineComponent } from 'vue';

export default defineComponent({
  name: 'FooBar',
  emits: ['fooBar'],
});
</script>
<template>
  <FooBar @foo-bar="onFooBar" />
</template>

If so, we need to turn off the vue/custom-event-name-casing rule and update the document.

@jameschenjav
Copy link
Author

jameschenjav commented Oct 29, 2020

thx. i will turn off vue/custom-event-name-casing for now.

Vue3 recommendation should be the other way around? XD

@jameschenjav
Copy link
Author

I still got an error with 'vue/custom-event-name-casing': 'off' in vscode:
image

But no longer got the error from cli.

I guess another bug report for Vetur?

@ota-meshi
Copy link
Member

You need to add vetur.validation.template: false to .vscode/settings.json.

https://eslint.vuejs.org/user-guide/#trouble-with-visual-studio-code

@jameschenjav
Copy link
Author

thx. i thought it would conflict with source.fixAll.eslint but seems works fine. its still formatting my template on save.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
2 participants