eslint-plugin-vue
eslint-plugin-vue copied to clipboard
Some rules are not working while using vue-class-component
My environment
- ESLint version:6.7.1
- eslint-plugin-vue version:6.0.1
- Node version:v11.14.0
Please show your full configuration:
module.exports = {
root: true,
env: {
node: true,
},
extends: [
// airbnb
'airbnb-base',
// vue lint
// https://github.com/vuejs/eslint-plugin-vue#priority-a-essential-error-prevention
'plugin:vue/recommended',
// https://github.com/typescript-eslint/typescript-eslint/tree/master/packages/eslint-plugin
'plugin:@typescript-eslint/recommended',
// prettier
'prettier',
'prettier/@typescript-eslint',
'prettier/vue',
'@vue/typescript'
],
plugins: [
// 'html'
],
rules: {
// ...
'no-multiple-empty-lines': ["error", { "max": 1 }],
// ===
'eqeqeq': ["error", "always"],
// max-len: 180
'max-len': ['error', 180],
// todo: vue/order-in-components, not working
// todo: vue/prop-name-casing , not working,
// todo: vue/no-async-in-computed-properties , not working
// todo: vue/no-duplicate-attributes ,not working
'vue/no-dupe-keys': ['error'], // still not working
/*--------------------- vue rules ---------------------*/
// Vue component naming,PascalCase:'MyComponent ',kebab-case:'my-component'
'vue/name-property-casing': ['error', 'PascalCase'],
// vue template naming,PascalCase:<MyComponent></MyComponent> kebab-case: '<my-component></my-component>'
'vue/component-name-in-template-casing': ['error', 'kebab-case'],
/*--------------------- ts rules ---------------------*/
'@typescript-eslint/no-unused-vars': ['error'],
// typescript-eslint
'@typescript-eslint/interface-name-prefix': 'off',
'@typescript-eslint/explicit-function-return-type': 'off',
},
parser: 'vue-eslint-parser',
parserOptions: {
'parser': '@typescript-eslint/parser',
'project': 'tsconfig.json',
'tsconfigRootDir': './',
'extraFileExtensions': ['.vue']
},
};
What did you do?
import { Vue } from "vue-property-decorator"
interface IState {
arr: []
}
interface IProps {
'prop-a': number
}
export default class Home extends Vue<IState, IProps> {
// todo:eslint message: string = 'hello'
message = 'hello'
activated () {
this.$el = 'nnn'
console.log('actived')
}
onClick (): void {
const message = 'dd'
console.log(message)
console.log(this.message)
const longStr = 'str1234567…………189190191……str1………189190191……189190191……str1234567…………18919019str1234567…………189190191……str1234567…………189190191……str1234567…………189190191……1……'
console.log(longStr)
}
get valA () {
return Promise.all([new Promise((resolve) => {resolve('hhh')})])
}
}
What did you expect to happen? It should show some errors.
What actually happened?
Nothing errors are shown.
More description I just import vue and typescript without using vue-cli. And i want using eslint-plugin-vue to lint my vue files which using vue-class-component.
I have the same problem.
When I use a classic mono file vue.js without "vue-property-decorator", it works:

But with "vue-property-decorator", it doesn't work.
The linter says nothing:

Regards.
Thank you for this issue.
Currently, this plugin does not support vue-class-component.
In order for this plugin to support vue-class-component, it is necessary to first identify the issues with each rule.
I want you to help with this task.
@ota-meshi class-component and property-decorator is not only used for typescript (but mostly).
Main issue is with helper functions, there is no support for classes in them, getComponentProps is good example of function like this.
https://github.com/vuejs/eslint-plugin-vue/blob/master/lib/utils/index.js#L430
in case of typescript + class some of rules are useless or they can be replaced by enforcing additional syntax on typescript, eg. if @Prop decorator is used we should require readonly property.
this eliminates need for rules that checks if prop value is mutated, this is validated by typescript if prop is readonly.
examples of rules that should be used in typescript + class:
require-readonly-prop
module.exports = {
meta: {
fixable: 'code'
},
create (context) {
function checkClassProperty (node) {
const parent = node.parent
if (parent.type === 'ClassProperty') {
if (!parent.readonly) {
context.report({
message: '@Prop decorator should be readonly',
node: parent.key,
fix (fixer) {
return fixer.insertTextBefore(parent.key, 'readonly ')
}
})
}
} else {
context.report({
message: '@Prop decorator can be present only on ClassProperty',
node
})
}
}
return {
"Decorator[expression.type='Identifier'][expression.name='Prop']" (node) {
checkClassProperty(node)
},
"Decorator[expression.type='CallExpression'][expression.callee.type='Identifier'][expression.callee.name='Prop']" (node) {
checkClassProperty(node)
}
}
}
}
no-undefined-data
module.exports = {
meta: {
fixable: undefined,
messages: {
error: 'Component data must have value, otherwise it\'s not going to be reactive'
}
},
create (context) {
function isUndefined (node) {
if (!node) {
return true
}
return node.type === 'Identifier' && node.name === 'undefined'
}
function hasComponentDecorator (node) {
if (!node || !node.decorators || !node.decorators.length) {
return false
}
return node.decorators.some((el) => {
return (
el.type === 'Decorator' &&
el.expression &&
(
(
el.expression.type === 'Identifier' &&
el.expression.name === 'Component'
) || (
el.expression.type === 'CallExpression' &&
el.expression.callee &&
el.expression.callee.type === 'Identifier' &&
el.expression.callee.name === 'Component'
)
)
)
})
}
return {
'ClassDeclaration > ClassBody > ClassProperty' (node) {
if (
(!node.decorators || !node.decorators.length) &&
hasComponentDecorator(node.parent.parent) &&
isUndefined(node.value)
) {
context.report({
messageId: 'error',
node
})
}
}
}
}
}
note: this is just example and they may not support all cases (they require
@Componentdecorator to be present on class level)
@ota-meshi "Currently, this plugin does not support vue-class-component." - Can you provide more information please? I do not know how this library performs the checks. Which rules(or in general) do not work for vue-class-component and why? I might look into helping fix this, but I am not sure where to start.
Another rule doesn't work: match-component-file-name
Doc: https://github.com/vuejs/eslint-plugin-vue/blob/master/docs/rules/match-component-file-name.md Issue: https://github.com/vuejs/eslint-plugin-vue/issues/667
<script lang="ts">
// components/Normal.vue
import { Component, Vue } from 'vue-property-decorator';
// @vue/component
@Component
export default class Lol extends Vue {
render(): null { return null; }
}
</script>
with the rule declared as
{
'vue/match-component-file-name': ['error', {
extensions: ['.vue', 'vue', 'vue.ts', 'jsx'],
shouldMatchCase: true,
}]
}
This is still an issue, are there plans to fix it?
Vue Class Component is no longer actively maintained and not recommended for Vue 3: https://class-component.vuejs.org/
This library is no longer actively maintained. It is no longer recommend to use Class-based components in Vue 3. The recommended way to use Vue 3 in large applications is Single-File Components, Composition API, and
<script setup>.
So I suggest to not invest time in eslint-plugin-vue to start supporting this.