In this issue, I will list the Vue.js 3.x changes that need to be supported by eslint-plugin-vue.
vue/valid-template-root to allow multiple root nodes.vue/no-multiple-template-root rule that disallows multiple root nodes (for Vue 2).v-bind's .sync modifier and replacing it with an argument on v-model. RFC0005vue/valid-v-model to allows argument (component only).vue/no-v-model-argument rule that disallows argument (for Vue 2).vue/no-deprecated-v-bind-sync rule that disallows v-bind.sync.vue/no-deprecated-functional-template rule that disallows <template functional>.app.component and app.mixin to utils/index.isVueComponent.v-model API changes RFC0011vue/valid-v-model rule to provide support for custom modifiers. https://github.com/vuejs/eslint-plugin-vue/issues/1035#issuecomment-578446775vue/no-custom-modifiers-on-v-model rule to checks if v-model does not contain custom modifiers (Vue 2 backward compatibility) https://github.com/vuejs/eslint-plugin-vue/issues/1035#issuecomment-578446775setup property to vue/order-in-components rule.vue/no-ref-as-operand rule. https://github.com/vuejs/eslint-plugin-vue/issues/1035#issuecomment-575315812vue/no-watch-after-await rule. https://github.com/vuejs/eslint-plugin-vue/issues/1035#issuecomment-575315812vue/no-lifecycle-after-await rule. https://github.com/vuejs/eslint-plugin-vue/issues/1035#issuecomment-575315812vue/no-setup-props-destructure rule. https://github.com/vuejs/eslint-plugin-vue/issues/1035#issuecomment-575315812vue/no-dupe-keys rule and vue/no-reserved-keys to handle setup.vue/no-deprecated-v-on-number-modifiers rule that disallows numbers as v-on modifiers.vue/no-deprecated-vue-config-keycodes rule that disallows Vue.config.keyCodes.vue/no-deprecated-filter rule that disallows Vue2 filter.inline-template. RFC0016vue/no-deprecated-inline-template rule that disallow inline-template attributtes.<transition> as component's root will no longer trigger transitions when the component is toggled from the outside.. RFC0017vue/require-v-if-inside-transition rule that checks whether expose a boolean prop to control the presence of content inside <transition>. e.g v-if, v-show. https://github.com/vuejs/eslint-plugin-vue/issues/1035#issuecomment-575229114data RFC0019vue/no-deprecated-data-object-declaration rule$on, $off and $once instance methods RFC0020vue/no-deprecated-events-api rulevue/no-deprecated-html-element-is rule that disallow the is attribute on HTML elements.emits property to vue/order-in-components rule.vue/require-explicit-emits rule that requires the emits option to have a name called by $emit().vue/return-in-emits-validator rule enforces that a return statement is present in emits validator.vue/no-deprecated-v-on-native-modifier rule that disallow .native modifier on v-on.vue/no-deprecated-dollar-listeners-api rule that disallow $listeners.List the changes after #1036 was merged.
essential for Vue 3vue/no-deprecated-filter rule.vue/no-deprecated-v-bind-sync rule.vue/no-deprecated-v-on-number-modifiers rule.vue/no-deprecated-data-object-declaration rulevue/no-deprecated-events-api rulevue/no-deprecated-inline-template rulevue/require-v-if-inside-transition rule.vue/no-ref-as-operand rule.vue/no-watch-after-await rule.vue/no-lifecycle-after-await rule.vue/no-setup-props-destructure rule.vue/no-deprecated-scope-attribute rule.vue/no-deprecated-slot-attribute rule.vue/no-deprecated-slot-scope-attribute rule.vue/valid-v-bind-sync rule.vue/no-deprecated-functional-template rule.vue/no-deprecated-html-element-is rule.vue/no-deprecated-vue-config-keycodes rule.vue/no-deprecated-v-on-native-modifier rule.vue/no-deprecated-dollar-listeners rule.vue/return-in-emits-validator rule.strongly-recommended for Vue 3recommended for Vue 3essential for Vue 2vue/no-multiple-template-root rule.vue/no-v-model-argument rule.vue/no-custom-modifiers-on-v-model rule.strongly-recommended for Vue 2recommended for Vue 2refs
https://medium.com/the-vue-point/plans-for-the-next-iteration-of-vue-js-777ffea6fabf
https://github.com/vuejs/rfcs/pulls?utf8=%E2%9C%93&q=is%3Apr+label%3A3.x+
https://vueschool.io/articles/vuejs-tutorials/exciting-new-features-in-vue-3/
https://vue-composition-api-rfc.netlify.com/
/cc @vuejs/docs
I think these changes are also to be addressed in the new style guide.
Any thoughts?
I think a require-v-if-inside-transition rule can be added for RFC0017
Some rules I had in mind:
no-ref-as-operand:
Detect cases where a ref is used incorrectly as an operand in binary operations. + is probably the most common case for such errors. For example:
const count = ref(0)
count++ // error
count + 1 // error
1 + count // error
A ref used as the condition in a ternary is probably also an error:
const ok = ref(true)
const msg = ok ? 'yes' : 'no' // error
no-watch-after-await & no-lifecycle-after-await:
In setup(), watch and onXXX lifecycle hooks should be registered synchronously. So their usage should be prohibited in async setup() after await statements:
async setup() {
watch(() => { /* ... */ }) // ok
onMounted(() => { /* ... */ }) // ok
await doSomething()
watch(() => { /* ... */ }) // error
onMounted(() => { /* ... */ }) // error
}
no-setup-props-destructure
Destructuring the props passed to setup will cause the value to lose reactivity.
// Do
setup(props) {
watch(() => {
console.log(props.count) // ok
})
return () => {
return h('div', props.count) // ok
}
}
// Don't
setup({ count }) { // error
watch(() => {
console.log(count) // not going to detect changes
})
return () => {
return h('div', count) // not going to update
}
}
Also, destructuring in root scope of setup() should error, but ok inside nested callbacks or returned render functions:
setup(props) {
const { count } = props // error
watch(() => {
const { count } = props // ok
console.log(count)
})
return () => {
const { count } = props // ok
return h('div', count)
}
}
@sodatea @yyx990803 Thank you for your comments!
I have added new rules to the list.
@michalsnik @mysticatea Could you comment on this issue if you have any feedback?
Hi! Thanks @ota-meshi @sodatea @yyx990803 for the work done with this plugin.
Will we be adding any rules for when consumers try to access refs in the template through .value? I feel like some people would try to do this, yet based on the RFC docs, Vue internally does this for you.
@codebender828 that's a good one, although a user may very well have an object with .value so we will need the component's type information to be able to warn without false positives.
I have a question about v-model changes. 馃檪
If i understood RFC 0011 right, v-model api will provide also support for custom modifiers.
Adding that feature wouldn't require also some changes to vue/valid-v-model rule?
Ex.:
vue/valid-v-model rule to provide support for custom modifiers.vue/no-custom-modifiers-on-v-model rule to checks if v-model does not contain custom modifiers (Vue 2 backward compatibility)Note that custom modifiers are only supported for v-model on custom components. Usage on native <input>, <select> and <textarea> still only support the built-in modifiers.
@przemkow Thank you for your comment. And thank you for your contribution.
I overlooked the custom modifiers change.
I think we need to change the valid-v-model rule and add new rule as you say.
@ota-meshi setup function should be added to vue/no-dupe-keys rule as well isn't it?
@przemkow I think it needs to be added as you say.
what about no this in setup function? I really miss that in eslint on vue2
I was thinking of adding something similar to react-hooks/exhaustive-deps that autofix in the return statement all the reactive and ref variables present in the setup function
Hi @chiptus @victorgarciaesgi. Sorry for the late reply.
Could you open a new issue and include sample code?
Because I don't understand your proposed rule correctly.
@ota-meshi Sure!
Consider this code in React
export function Component() {
const isMobile = useMedia({ maxWidth: '768px' })
useEffect(() => {
if (isMobile) {
console.log(isMobile)
}
})
return <div>{isMobile}</div>
}
With the rule react-hooks/exhaustive-deps, eslint will autofix the code to add missing deps to useEffect, resulting in:
useEffect(() => {
if (isMobile) {
console.log(isMobile)
}
}, [isMobile])
In Vue3 we can have the same thing but for the return statement in setup
Exemple:
export default defineComponent({
setup(props, ctx) {
const search = ref('')
}
})
Will become:
export default defineComponent({
setup(props, ctx) {
const search = ref('')
return {search}
}
})
I'm not too sure about this. I'm pretty sure we will rather often have state in setup that doesn't have to be exposed to the template.
@LinusBorg Yeah i thought of that too, maybe complete the return statement with only values present in the template?
Does we need about no-this-in-setup rule?
We also need a vue/no-inline-template for RFC0016: Remove inline-template
Hi @sodatea. I haven't used the inline-template and I'm not familiar with it.
Can the inline-template be used in SFC?
Yeah, it can be used in SFC.
I did not know that. Thank you!
Per RFC0007, I think a no-functional-template rule is needed. I'm not sure if it's auto-fixable though.
I just found out that the no-reserved-component-names rule does not throw on Vue's own built-in component names like transition, transition-group, keep-alive and component. As of Vue.js 3.x, teleport should be added to the list too.
Per RFC0027, we need a new rule to restrict the is prop usage to the reserved <component> tag only.
The vue/no-deprecated-v-on-number-modifiers rule needs to also detect the usage of Vue.config.keyCodes and warn the deprecation.
@sodatea Thank you for suggesting the rules and changes.
I will make those changes.
Thanks!
Currently this plugin has finished implementing most of the rules defined in this issue.
Open the remaining issue with another and close this issue.
If you would like to propose a new rule, please open a new issue.
@ota-meshi thanks for the hard work!
Most helpful comment
Some rules I had in mind:
no-ref-as-operand:Detect cases where a
refis used incorrectly as an operand in binary operations.+is probably the most common case for such errors. For example:A ref used as the condition in a ternary is probably also an error:
no-watch-after-await&no-lifecycle-after-await:In
setup(),watchandonXXXlifecycle hooks should be registered synchronously. So their usage should be prohibited inasync setup()afterawaitstatements:no-setup-props-destructureDestructuring the
propspassed tosetupwill cause the value to lose reactivity.Also, destructuring in root scope of
setup()should error, but ok inside nested callbacks or returned render functions: