Skip to content

Commit a12f2d9

Browse files
authored
Add vue/no-deprecated-destroyed-lifecycle rule (#1211)
* Add `vue/no-deprecated-destroyed-lifecycle` rule * Add testcases and fix bug
1 parent b57a273 commit a12f2d9

File tree

6 files changed

+524
-0
lines changed

6 files changed

+524
-0
lines changed

Diff for: docs/rules/README.md

+1
Original file line numberDiff line numberDiff line change
@@ -42,6 +42,7 @@ Enforce all the rules in this category, as well as all higher priority rules, wi
4242
| [vue/no-arrow-functions-in-watch](./no-arrow-functions-in-watch.md) | disallow using arrow functions to define watcher | |
4343
| [vue/no-async-in-computed-properties](./no-async-in-computed-properties.md) | disallow asynchronous actions in computed properties | |
4444
| [vue/no-deprecated-data-object-declaration](./no-deprecated-data-object-declaration.md) | disallow using deprecated object declaration on data (in Vue.js 3.0.0+) | :wrench: |
45+
| [vue/no-deprecated-destroyed-lifecycle](./no-deprecated-destroyed-lifecycle.md) | disallow using deprecated `destroyed` and `beforeDestroy` lifecycle hooks (in Vue.js 3.0.0+) | |
4546
| [vue/no-deprecated-dollar-listeners-api](./no-deprecated-dollar-listeners-api.md) | disallow using deprecated `$listeners` (in Vue.js 3.0.0+) | |
4647
| [vue/no-deprecated-dollar-scopedslots-api](./no-deprecated-dollar-scopedslots-api.md) | disallow using deprecated `$scopedSlots` (in Vue.js 3.0.0+) | :wrench: |
4748
| [vue/no-deprecated-events-api](./no-deprecated-events-api.md) | disallow using deprecated events api (in Vue.js 3.0.0+) | |

Diff for: docs/rules/no-deprecated-destroyed-lifecycle.md

+43
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,43 @@
1+
---
2+
pageClass: rule-details
3+
sidebarDepth: 0
4+
title: vue/no-deprecated-destroyed-lifecycle
5+
description: disallow using deprecated `destroyed` and `beforeDestroy` lifecycle hooks (in Vue.js 3.0.0+)
6+
---
7+
# vue/no-deprecated-destroyed-lifecycle
8+
> disallow using deprecated `destroyed` and `beforeDestroy` lifecycle hooks (in Vue.js 3.0.0+)
9+
10+
- :gear: This rule is included in all of `"plugin:vue/vue3-essential"`, `"plugin:vue/vue3-strongly-recommended"` and `"plugin:vue/vue3-recommended"`.
11+
12+
## :book: Rule Details
13+
14+
This rule reports use of deprecated `destroyed` and `beforeDestroy` lifecycle hooks. (in Vue.js 3.0.0+).
15+
16+
<eslint-code-block :rules="{'vue/no-deprecated-destroyed-lifecycle': ['error']}">
17+
18+
```vue
19+
<script>
20+
export default {
21+
/* ✓ GOOD */
22+
beforeMount () {},
23+
mounted () {},
24+
beforeUnmount () {},
25+
unmounted () {},
26+
27+
/* ✗ BAD */
28+
beforeDestroy () {},
29+
destroyed () {}
30+
}
31+
</script>
32+
```
33+
34+
</eslint-code-block>
35+
36+
## :wrench: Options
37+
38+
Nothing.
39+
40+
## :mag: Implementation
41+
42+
- [Rule source](https://github.com/vuejs/eslint-plugin-vue/blob/master/lib/rules/no-deprecated-destroyed-lifecycle.js)
43+
- [Test source](https://github.com/vuejs/eslint-plugin-vue/blob/master/tests/lib/rules/no-deprecated-destroyed-lifecycle.js)

Diff for: lib/configs/vue3-essential.js

+1
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,7 @@ module.exports = {
1010
'vue/no-arrow-functions-in-watch': 'error',
1111
'vue/no-async-in-computed-properties': 'error',
1212
'vue/no-deprecated-data-object-declaration': 'error',
13+
'vue/no-deprecated-destroyed-lifecycle': 'error',
1314
'vue/no-deprecated-dollar-listeners-api': 'error',
1415
'vue/no-deprecated-dollar-scopedslots-api': 'error',
1516
'vue/no-deprecated-events-api': 'error',

Diff for: lib/index.js

+1
Original file line numberDiff line numberDiff line change
@@ -51,6 +51,7 @@ module.exports = {
5151
'no-confusing-v-for-v-if': require('./rules/no-confusing-v-for-v-if'),
5252
'no-custom-modifiers-on-v-model': require('./rules/no-custom-modifiers-on-v-model'),
5353
'no-deprecated-data-object-declaration': require('./rules/no-deprecated-data-object-declaration'),
54+
'no-deprecated-destroyed-lifecycle': require('./rules/no-deprecated-destroyed-lifecycle'),
5455
'no-deprecated-dollar-listeners-api': require('./rules/no-deprecated-dollar-listeners-api'),
5556
'no-deprecated-dollar-scopedslots-api': require('./rules/no-deprecated-dollar-scopedslots-api'),
5657
'no-deprecated-events-api': require('./rules/no-deprecated-events-api'),

Diff for: lib/rules/no-deprecated-destroyed-lifecycle.js

+101
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,101 @@
1+
/**
2+
* @author Yosuke Ota
3+
* See LICENSE file in root directory for full license.
4+
*/
5+
'use strict'
6+
7+
// ------------------------------------------------------------------------------
8+
// Requirements
9+
// ------------------------------------------------------------------------------
10+
11+
const utils = require('../utils')
12+
13+
// ------------------------------------------------------------------------------
14+
// Rule Definition
15+
// ------------------------------------------------------------------------------
16+
17+
module.exports = {
18+
meta: {
19+
type: 'problem',
20+
docs: {
21+
description:
22+
'disallow using deprecated `destroyed` and `beforeDestroy` lifecycle hooks (in Vue.js 3.0.0+)',
23+
categories: ['vue3-essential'],
24+
url:
25+
'https://eslint.vuejs.org/rules/no-deprecated-destroyed-lifecycle.html'
26+
},
27+
fixable: null,
28+
schema: [],
29+
messages: {
30+
deprecatedDestroyed:
31+
'The `destroyed` lifecycle hook is deprecated. Use `unmounted` instead.',
32+
deprecatedBeforeDestroy:
33+
'The `beforeDestroy` lifecycle hook is deprecated. Use `beforeUnmount` instead.',
34+
insteadUnmounted: 'Instead, change to `unmounted`.',
35+
insteadBeforeUnmount: 'Instead, change to `beforeUnmount`.'
36+
}
37+
},
38+
/** @param {RuleContext} context */
39+
create(context) {
40+
return utils.executeOnVue(context, (obj) => {
41+
const destroyed = utils.findProperty(obj, 'destroyed')
42+
43+
if (destroyed) {
44+
context.report({
45+
node: destroyed.key,
46+
messageId: 'deprecatedDestroyed',
47+
// I don't know if they have exactly the same function, so don't do autofix.
48+
suggest: [
49+
{
50+
messageId: 'insteadUnmounted',
51+
fix(fixer) {
52+
return fix(fixer, destroyed, 'unmounted')
53+
}
54+
}
55+
]
56+
})
57+
}
58+
59+
const beforeDestroy = utils.findProperty(obj, 'beforeDestroy')
60+
if (beforeDestroy) {
61+
context.report({
62+
node: beforeDestroy.key,
63+
messageId: 'deprecatedBeforeDestroy',
64+
// I don't know if they have exactly the same function, so don't do autofix.
65+
suggest: [
66+
{
67+
messageId: 'insteadBeforeUnmount',
68+
fix(fixer) {
69+
return fix(fixer, beforeDestroy, 'beforeUnmount')
70+
}
71+
}
72+
]
73+
})
74+
}
75+
76+
/**
77+
* @param {RuleFixer} fixer
78+
* @param {Property} property
79+
* @param {string} newName
80+
*/
81+
function fix(fixer, property, newName) {
82+
if (property.computed) {
83+
if (
84+
property.key.type === 'Literal' ||
85+
property.key.type === 'TemplateLiteral'
86+
) {
87+
return fixer.replaceTextRange(
88+
[property.key.range[0] + 1, property.key.range[1] - 1],
89+
newName
90+
)
91+
}
92+
return null
93+
}
94+
if (property.shorthand) {
95+
return fixer.insertTextBefore(property.key, `${newName}:`)
96+
}
97+
return fixer.replaceText(property.key, newName)
98+
}
99+
})
100+
}
101+
}

0 commit comments

Comments
 (0)