diff --git a/docs/rules/README.md b/docs/rules/README.md index e229c19fc..3e37fe70b 100644 --- a/docs/rules/README.md +++ b/docs/rules/README.md @@ -39,6 +39,7 @@ Enforce all the rules in this category, as well as all higher priority rules, wi | Rule ID | Description | | |:--------|:------------|:---| | [vue/no-async-in-computed-properties](./no-async-in-computed-properties.md) | disallow asynchronous actions in computed properties | | +| [vue/no-deprecated-events-api](./no-deprecated-events-api.md) | disallow using deprecated events api | | | [vue/no-deprecated-data-object-declaration](./no-deprecated-data-object-declaration.md) | disallow using deprecated object declaration on data | :wrench: | | [vue/no-deprecated-filter](./no-deprecated-filter.md) | disallow using deprecated filters syntax | | | [vue/no-deprecated-scope-attribute](./no-deprecated-scope-attribute.md) | disallow deprecated `scope` attribute (in Vue.js 2.5.0+) | :wrench: | diff --git a/docs/rules/no-deprecated-events-api.md b/docs/rules/no-deprecated-events-api.md new file mode 100644 index 000000000..e855a5a4f --- /dev/null +++ b/docs/rules/no-deprecated-events-api.md @@ -0,0 +1,57 @@ +--- +pageClass: rule-details +sidebarDepth: 0 +title: vue/no-deprecated-events-api +description: disallow using deprecated events api +--- +# vue/no-deprecated-events-api +> disallow using deprecated events api + +- :gear: This rule is included in all of `"plugin:vue/vue3-essential"`, `"plugin:vue/vue3-strongly-recommended"` and `"plugin:vue/vue3-recommended"`. + +## :book: Rule Details + +This rule reports use of deprecated `$on`, `$off` `$once` api. (in Vue.js 3.0.0+). + + + +```vue + +``` + + + +## :wrench: Options + +Nothing. + +## :books: Further reading + +- [RFC: events api change](https://github.com/vuejs/rfcs/blob/master/active-rfcs/0020-events-api-change.md) + +## :mag: Implementation + +- [Rule source](https://github.com/vuejs/eslint-plugin-vue/blob/master/lib/rules/no-deprecated-events-api.js) +- [Test source](https://github.com/vuejs/eslint-plugin-vue/blob/master/tests/lib/rules/no-deprecated-events-api.js) diff --git a/lib/configs/vue3-essential.js b/lib/configs/vue3-essential.js index 3f2865dfa..f7c35fecf 100644 --- a/lib/configs/vue3-essential.js +++ b/lib/configs/vue3-essential.js @@ -7,6 +7,7 @@ module.exports = { extends: require.resolve('./base'), rules: { 'vue/no-async-in-computed-properties': 'error', + 'vue/no-deprecated-events-api': 'error', 'vue/no-deprecated-data-object-declaration': 'error', 'vue/no-deprecated-filter': 'error', 'vue/no-deprecated-scope-attribute': 'error', diff --git a/lib/index.js b/lib/index.js index 040965de0..03fd799a2 100644 --- a/lib/index.js +++ b/lib/index.js @@ -40,6 +40,7 @@ module.exports = { 'no-boolean-default': require('./rules/no-boolean-default'), 'no-confusing-v-for-v-if': require('./rules/no-confusing-v-for-v-if'), 'no-custom-modifiers-on-v-model': require('./rules/no-custom-modifiers-on-v-model'), + 'no-deprecated-events-api': require('./rules/no-deprecated-events-api'), 'no-deprecated-data-object-declaration': require('./rules/no-deprecated-data-object-declaration'), 'no-deprecated-filter': require('./rules/no-deprecated-filter'), 'no-deprecated-scope-attribute': require('./rules/no-deprecated-scope-attribute'), diff --git a/lib/rules/no-deprecated-events-api.js b/lib/rules/no-deprecated-events-api.js new file mode 100644 index 000000000..488b893d3 --- /dev/null +++ b/lib/rules/no-deprecated-events-api.js @@ -0,0 +1,57 @@ +/** + * @fileoverview disallow using deprecated events api + * @author yoyo930021 + */ +'use strict' + +// ------------------------------------------------------------------------------ +// Requirements +// ------------------------------------------------------------------------------ + +const utils = require('../utils') + +// ------------------------------------------------------------------------------ +// Rule Definition +// ------------------------------------------------------------------------------ + +module.exports = { + meta: { + type: 'problem', + docs: { + description: 'disallow using deprecated events api', + categories: ['vue3-essential'], + url: 'https://eslint.vuejs.org/rules/no-deprecated-events-api.html' + }, + fixable: null, + schema: [], + messages: { + noDeprecatedEventsApi: 'The Events api `$on`, `$off` `$once` is deprecated. Using external library instead, for example mitt.' + } + }, + + create (context) { + const forbiddenNodes = [] + + return Object.assign( + { + 'CallExpression > MemberExpression > ThisExpression' (node) { + if (!['$on', '$off', '$once'].includes(node.parent.property.name)) return + forbiddenNodes.push(node.parent.parent) + } + }, + utils.executeOnVue(context, (obj) => { + forbiddenNodes.forEach(node => { + if ( + node.loc.start.line >= obj.loc.start.line && + node.loc.end.line <= obj.loc.end.line + ) { + context.report({ + node, + messageId: 'noDeprecatedEventsApi' + }) + } + }) + }) + ) + } +} diff --git a/tests/lib/rules/no-deprecated-events-api.js b/tests/lib/rules/no-deprecated-events-api.js new file mode 100644 index 000000000..59a6c685f --- /dev/null +++ b/tests/lib/rules/no-deprecated-events-api.js @@ -0,0 +1,161 @@ +/* eslint-disable eslint-plugin/consistent-output */ +/** + * @fileoverview disallow using deprecated events api + * @author yoyo930021 + */ +'use strict' + +// ------------------------------------------------------------------------------ +// Requirements +// ------------------------------------------------------------------------------ + +const rule = require('../../../lib/rules/no-deprecated-events-api') + +const RuleTester = require('eslint').RuleTester + +const parserOptions = { + ecmaVersion: 2018, + sourceType: 'module' +} + +// ------------------------------------------------------------------------------ +// Tests +// ------------------------------------------------------------------------------ + +const ruleTester = new RuleTester() +ruleTester.run('no-deprecated-events-api', rule, { + + valid: [ + { + filename: 'test.js', + code: ` + createApp({ + mounted () { + this.$emit('start') + } + }) + `, + parserOptions + }, + { + filename: 'test.js', + code: ` + createApp({ + methods: { + click () { + this.$emit('click') + } + } + }) + `, + parserOptions + }, + { + filename: 'test.js', + code: ` + const another = function () { + this.$on('start', args => { + console.log('start') + }) + } + + createApp({ + mounted () { + this.$emit('start') + } + }) + `, + parserOptions + }, + { + filename: 'test.js', + code: ` + app.component('some-comp', { + mounted () { + this.$emit('start') + } + }) + `, + parserOptions + }, + { + filename: 'test.vue', + code: ` + export default { + mounted () { + this.$emit('start') + } + } + `, + parserOptions + }, + { + filename: 'test.vue', + code: ` + import mitt from 'mitt' + const emitter = mitt() + + export default { + setup () { + emitter.on('foo', e => console.log('foo', e)) + emitter.emit('foo', { a: 'b' }) + emitter.off('foo', onFoo) + } + } + `, + parserOptions + } + ], + + invalid: [ + { + filename: 'test.js', + code: ` + app.component('some-comp', { + mounted () { + this.$on('start', function (args) { + console.log('start', args) + }) + } + }) + `, + parserOptions, + errors: [{ + message: 'The Events api `$on`, `$off` `$once` is deprecated. Using external library instead, for example mitt.', + line: 4 + }] + }, + { + filename: 'test.js', + code: ` + app.component('some-comp', { + mounted () { + this.$off('start') + } + }) + `, + parserOptions, + errors: [{ + message: 'The Events api `$on`, `$off` `$once` is deprecated. Using external library instead, for example mitt.', + line: 4 + }] + }, + { + filename: 'test.vue', + code: ` + export default { + mounted () { + this.$once('start', function () { + console.log('start') + }) + } + } + `, + parserOptions, + errors: [{ + message: 'The Events api `$on`, `$off` `$once` is deprecated. Using external library instead, for example mitt.', + line: 4 + }] + } + ] +})