Skip to content

Commit 8f4c945

Browse files
committed
Add component-data rule.
1 parent 1d00dd6 commit 8f4c945

File tree

6 files changed

+216
-7
lines changed

6 files changed

+216
-7
lines changed

docs/rules/component-data.md

Lines changed: 33 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,33 @@
1+
# Enforces that a component data must be a function (component-data)
2+
3+
When using the data property on a component (i.e. anywhere except on `new Vue`), the value must be a function that returns an object.
4+
5+
## :book: Rule Details
6+
7+
When the value of `data` is an object, it’s shared across all instances of a component.
8+
9+
:-1: Examples of **incorrect** code for this rule:
10+
11+
```js
12+
Vue.component('some-comp', {
13+
data: {
14+
foo: 'bar'
15+
}
16+
})
17+
```
18+
19+
:+1: Examples of **correct** code for this rule:
20+
21+
```js
22+
Vue.component('some-comp', {
23+
data: function () {
24+
return {
25+
foo: 'bar'
26+
}
27+
}
28+
})
29+
```
30+
31+
## :wrench: Options
32+
33+
Nothing.

lib/rules/component-data.js

Lines changed: 57 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,57 @@
1+
/**
2+
* @fileoverview When using the data property on a component (i.e. anywhere except on new Vue), the value must be a function that returns an object.
3+
* @author Armano
4+
*/
5+
'use strict'
6+
7+
const utils = require('../utils')
8+
9+
function create (context) {
10+
// variables should be defined here
11+
12+
// ----------------------------------------------------------------------
13+
// Helpers
14+
// ----------------------------------------------------------------------
15+
16+
// any helper functions should go here or else delete this section
17+
18+
// ----------------------------------------------------------------------
19+
// Public
20+
// ----------------------------------------------------------------------
21+
22+
return Object.assign({},
23+
utils.executeOnVueComponent(context, (obj) => {
24+
obj.properties
25+
.filter(p =>
26+
p.key.type === 'Identifier' &&
27+
p.key.name === 'data' &&
28+
p.value.type !== 'FunctionExpression'
29+
).forEach(cp => {
30+
context.report({
31+
node: cp.value,
32+
message: 'Component `data` must be a function.'
33+
})
34+
})
35+
})
36+
)
37+
}
38+
39+
// ------------------------------------------------------------------------------
40+
// Rule Definition
41+
// ------------------------------------------------------------------------------
42+
43+
module.exports = {
44+
meta: {
45+
docs: {
46+
description: 'Enforces that a component data must be a function',
47+
category: 'Possible Errors',
48+
recommended: false
49+
},
50+
fixable: null, // or "code" or "whitespace"
51+
schema: [
52+
// fill in your schema
53+
]
54+
},
55+
56+
create
57+
}

lib/rules/no-side-effects-in-computed-properties.js

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -33,7 +33,7 @@ function create (context) {
3333
}
3434
}
3535
},
36-
utils.executeOnVueComponent(context, (obj) => {
36+
utils.executeOnVue(context, (obj) => {
3737
const computedProperties = utils.getComputedProperties(obj)
3838

3939
computedProperties.forEach(cp => {

lib/rules/order-in-components.js

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -80,7 +80,7 @@ function create (context) {
8080
const extendedOrder = order.map(property => groups[property] || property)
8181
const orderMap = getOrderMap(extendedOrder)
8282

83-
return utils.executeOnVueComponent(context, (obj) => {
83+
return utils.executeOnVue(context, (obj) => {
8484
checkOrder(obj.properties, orderMap, context)
8585
})
8686
}

lib/utils/index.js

Lines changed: 19 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -363,6 +363,25 @@ module.exports = {
363363
node.arguments[0].type === 'ObjectExpression'
364364
},
365365

366+
executeOnVue (context, cb) {
367+
return Object.assign(
368+
this.executeOnVueComponent(context, cb),
369+
this.executeOnVueInstance(context, cb)
370+
)
371+
},
372+
373+
executeOnVueInstance (context, cb) {
374+
const _this = this
375+
376+
return {
377+
'NewExpression:exit' (node) {
378+
// new Vue({})
379+
if (!_this.isVueInstance(node)) return
380+
cb(node.arguments[0])
381+
}
382+
}
383+
},
384+
366385
executeOnVueComponent (context, cb) {
367386
const filePath = context.getFilename()
368387
const _this = this
@@ -377,11 +396,6 @@ module.exports = {
377396
// Vue.component('xxx', {}) || component('xxx', {})
378397
if (!_this.isVueComponent(node)) return
379398
cb(node.arguments.slice(-1)[0])
380-
},
381-
'NewExpression:exit' (node) {
382-
// new Vue({})
383-
if (!_this.isVueInstance(node)) return
384-
cb(node.arguments[0])
385399
}
386400
}
387401
}

tests/lib/rules/component-data.js

Lines changed: 105 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,105 @@
1+
/**
2+
* @fileoverview When using the data property on a component (i.e. anywhere except on new Vue), the value must be a function that returns an object.
3+
* @author Armano
4+
*/
5+
'use strict'
6+
7+
// ------------------------------------------------------------------------------
8+
// Requirements
9+
// ------------------------------------------------------------------------------
10+
11+
var rule = require('../../../lib/rules/component-data')
12+
13+
const RuleTester = require('eslint').RuleTester
14+
15+
// ------------------------------------------------------------------------------
16+
// Tests
17+
// ------------------------------------------------------------------------------
18+
19+
var ruleTester = new RuleTester()
20+
ruleTester.run('component-data', rule, {
21+
22+
valid: [
23+
{
24+
filename: 'test.js',
25+
code: `
26+
new Vue({
27+
data: function () {
28+
return {
29+
foo: 'bar'
30+
}
31+
}
32+
})
33+
`
34+
},
35+
{
36+
filename: 'test.js',
37+
code: `
38+
new Vue({
39+
data: {
40+
foo: 'bar'
41+
}
42+
})
43+
`
44+
},
45+
{
46+
filename: 'test.js',
47+
code: `
48+
Vue.component('some-comp', {
49+
data: function () {
50+
return {
51+
foo: 'bar'
52+
}
53+
}
54+
})
55+
`,
56+
parserOptions: { ecmaVersion: 6 }
57+
},
58+
{
59+
filename: 'test.vue',
60+
code: `
61+
export default {
62+
data: function () {
63+
return {
64+
foo: 'bar'
65+
}
66+
}
67+
}
68+
`,
69+
parserOptions: { ecmaVersion: 6, sourceType: 'module' }
70+
}
71+
],
72+
73+
invalid: [
74+
{
75+
filename: 'test.js',
76+
code: `
77+
Vue.component('some-comp', {
78+
data: {
79+
foo: 'bar'
80+
}
81+
})
82+
`,
83+
parserOptions: { ecmaVersion: 6 },
84+
errors: [{
85+
message: 'Component `data` must be a function.',
86+
line: 3
87+
}]
88+
},
89+
{
90+
filename: 'test.vue',
91+
code: `
92+
export default {
93+
data: {
94+
foo: 'bar'
95+
}
96+
}
97+
`,
98+
parserOptions: { ecmaVersion: 6, sourceType: 'module' },
99+
errors: [{
100+
message: 'Component `data` must be a function.',
101+
line: 3
102+
}]
103+
}
104+
]
105+
})

0 commit comments

Comments
 (0)