Skip to content
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.

Commit 91da522

Browse files
committedJun 8, 2024·
feat(v-on-handler-style): add allowInlineFuncSingleArg option
1 parent 769b09f commit 91da522

File tree

3 files changed

+255
-46
lines changed

3 files changed

+255
-46
lines changed
 

‎docs/rules/v-on-handler-style.md

+37-1
Original file line numberDiff line numberDiff line change
@@ -63,6 +63,7 @@ This rule aims to enforce a consistent style in `v-on` event handlers:
6363
- `"inline"` ... Allow inline handlers. e.g. `v-on:click="handler()"`
6464
- Second option
6565
- `ignoreIncludesComment` ... If `true`, do not report inline handlers or inline functions containing comments, even if the preferred style is `"method"`. Default is `false`.
66+
- `allowInlineFuncSingleArg` ... Used in conjunction with `["method", "inline-function"]` or `["inline", "inline-function"]`. If `true`, allow inline functions with a single argument. Default is `false`.
6667

6768
### `["method", "inline-function"]` (Default)
6869

@@ -126,24 +127,59 @@ This rule aims to enforce a consistent style in `v-on` event handlers:
126127

127128
<eslint-code-block fix :rules="{'vue/v-on-handler-style': ['error', ['inline', 'inline-function']]}">
128129

130+
```vue
131+
<template>
132+
<!-- ✓ GOOD -->
133+
<button v-on:click="count++" />
134+
<button v-on:click="handler()" />
135+
<button v-on:click="handler($event)" />
136+
<button v-on:click="(arg1, arg2) => handler(arg1, arg2)" />
137+
<template v-for="e in list">
138+
<button v-on:click="handler(e)" />
139+
<button v-on:click="handler($event, e)" />
140+
<button v-on:click="(arg1, arg2) => handler(arg1, arg2, e)" />
141+
</template>
142+
143+
<!-- ✗ BAD -->
144+
<button v-on:click="() => count++" />
145+
<button v-on:click="handler" />
146+
<button v-on:click="() => handler()" />
147+
<button v-on:click="(arg) => handler(arg)" />
148+
<template v-for="e in list">
149+
<button v-on:click="() => handler(e)" />
150+
<button v-on:click="(arg) => handler(arg, e)" />
151+
</template>
152+
</template>
153+
```
154+
155+
</eslint-code-block>
156+
157+
### `["inline", "inline-function"]` with `allowInlineFuncSingleArg: true`
158+
159+
<eslint-code-block fix :rules="{'vue/v-on-handler-style': ['error', ['inline', 'inline-function'], { allowInlineFuncSingleArg: true }]}">
160+
129161
```vue
130162
<template>
131163
<!-- ✓ GOOD -->
132164
<button v-on:click="count++" />
133165
<button v-on:click="handler()" />
134166
<button v-on:click="handler($event)" />
135167
<button v-on:click="(arg) => handler(arg)" />
168+
<button v-on:click="(arg1, arg2) => handler(arg1, arg2)" />
136169
<template v-for="e in list">
137170
<button v-on:click="handler(e)" />
138171
<button v-on:click="handler($event, e)" />
139172
<button v-on:click="(arg) => handler(arg, e)" />
173+
<button v-on:click="(arg1, arg2) => handler(arg1, arg2, e)" />
140174
</template>
141175
142176
<!-- ✗ BAD -->
143177
<button v-on:click="() => count++" />
144178
<button v-on:click="handler" />
145179
<button v-on:click="() => handler()" />
146-
<button v-on:click="() => handler($event)" />
180+
<template v-for="e in list">
181+
<button v-on:click="() => handler(e)" />
182+
</template>
147183
</template>
148184
```
149185

‎lib/rules/v-on-handler-style.js

+86-42
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,7 @@ const utils = require('../utils')
1111
* @typedef {'method' | 'inline' | 'inline-function'} HandlerKind
1212
* @typedef {object} ObjectOption
1313
* @property {boolean} [ignoreIncludesComment]
14+
* @property {boolean} [allowInlineFuncSingleArg]
1415
*/
1516

1617
/**
@@ -33,8 +34,9 @@ function parseOptions(context) {
3334

3435
const option = options[1] || {}
3536
const ignoreIncludesComment = !!option.ignoreIncludesComment
37+
const allowInlineFuncSingleArg = option.allowInlineFuncSingleArg === true
3638

37-
return { allows, ignoreIncludesComment }
39+
return { allows, ignoreIncludesComment, allowInlineFuncSingleArg }
3840
}
3941

4042
/**
@@ -112,41 +114,73 @@ module.exports = {
112114
url: 'https://eslint.vuejs.org/rules/v-on-handler-style.html'
113115
},
114116
fixable: 'code',
115-
schema: [
116-
{
117-
oneOf: [
118-
{ enum: ['inline', 'inline-function'] },
119-
{
120-
type: 'array',
121-
items: [
122-
{ const: 'method' },
123-
{ enum: ['inline', 'inline-function'] }
124-
],
125-
uniqueItems: true,
126-
additionalItems: false,
127-
minItems: 2,
128-
maxItems: 2
129-
},
130-
{
131-
type: 'array',
132-
items: [{ const: 'inline' }, { const: 'inline-function' }],
133-
uniqueItems: true,
134-
additionalItems: false,
135-
minItems: 2,
136-
maxItems: 2
137-
}
138-
]
139-
},
140-
{
141-
type: 'object',
142-
properties: {
143-
ignoreIncludesComment: {
144-
type: 'boolean'
145-
}
117+
schema: {
118+
anyOf: [
119+
// `inline`, `inline-function` or `['method', 'inline']`
120+
{
121+
type: 'array',
122+
items: [
123+
{
124+
anyOf: [
125+
{ enum: ['inline', 'inline-function'] },
126+
{
127+
type: 'array',
128+
items: [{ const: 'method' }, { const: 'inline' }],
129+
uniqueItems: true,
130+
additionalItems: false,
131+
minItems: 2,
132+
maxItems: 2
133+
}
134+
]
135+
},
136+
{
137+
type: 'object',
138+
properties: {
139+
ignoreIncludesComment: {
140+
type: 'boolean'
141+
}
142+
},
143+
additionalProperties: false
144+
}
145+
],
146+
additionalItems: false,
147+
minItems: 1,
148+
maxItems: 2
146149
},
147-
additionalProperties: false
148-
}
149-
],
150+
// `['method', 'inline-function']` or `['inline', 'inline-function']`
151+
{
152+
type: 'array',
153+
items: [
154+
{
155+
type: 'array',
156+
items: [
157+
{ enum: ['method', 'inline'] },
158+
{ const: 'inline-function' }
159+
],
160+
uniqueItems: true,
161+
additionalItems: false,
162+
minItems: 2,
163+
maxItems: 2
164+
},
165+
{
166+
type: 'object',
167+
properties: {
168+
ignoreIncludesComment: {
169+
type: 'boolean'
170+
},
171+
allowInlineFuncSingleArg: {
172+
type: 'boolean'
173+
}
174+
},
175+
additionalProperties: false
176+
}
177+
],
178+
additionalItems: false,
179+
minItems: 0,
180+
maxItems: 2
181+
}
182+
]
183+
},
150184
messages: {
151185
preferMethodOverInline:
152186
'Prefer method handler over inline handler in v-on.',
@@ -170,7 +204,8 @@ module.exports = {
170204
},
171205
/** @param {RuleContext} context */
172206
create(context) {
173-
const { allows, ignoreIncludesComment } = parseOptions(context)
207+
const { allows, ignoreIncludesComment, allowInlineFuncSingleArg } =
208+
parseOptions(context)
174209

175210
/** @type {Set<VElement>} */
176211
const upperElements = new Set()
@@ -535,14 +570,23 @@ module.exports = {
535570
case 'ArrowFunctionExpression':
536571
case 'FunctionExpression': {
537572
// e.g. v-on:click="()=>foo()"
538-
if (
539-
allows[0] === 'inline-function' ||
540-
(allows[0] === 'inline' &&
541-
allows[1] === 'inline-function' &&
542-
expression.params.length > 0)
543-
) {
573+
if (allows[0] === 'inline-function') {
544574
return
545575
}
576+
577+
if (allows[1] === 'inline-function') {
578+
if (expression.params.length > 1) {
579+
return
580+
}
581+
582+
if (
583+
expression.params.length === 1 &&
584+
allowInlineFuncSingleArg
585+
) {
586+
return
587+
}
588+
}
589+
546590
for (const allow of allows) {
547591
if (verifyForInlineFunction(expression, allow)) {
548592
return

‎tests/lib/rules/v-on-handler-style.js

+132-3
Original file line numberDiff line numberDiff line change
@@ -72,6 +72,21 @@ tester.run('v-on-handler-style', rule, {
7272
filename: 'test.vue',
7373
code: '<template><button :click="foo()" /></template>'
7474
},
75+
{
76+
filename: 'test.vue',
77+
code: `<template>
78+
<button @click="value++" />
79+
<button @click="foo()" />
80+
<button @click="foo($event)" />
81+
<button @click="(a, b) => foo(a, b)" />
82+
<template v-for="e in list">
83+
<button @click="foo(e)" />
84+
<button @click="foo($event, e)" />
85+
<button @click="(a, b) => foo(a, b, e)" />
86+
</template>
87+
</template>`,
88+
options: [['inline', 'inline-function']]
89+
},
7590
{
7691
filename: 'test.vue',
7792
code: `<template>
@@ -87,7 +102,10 @@ tester.run('v-on-handler-style', rule, {
87102
<button @click="(a, b) => foo(a, b, e)" />
88103
</template>
89104
</template>`,
90-
options: [['inline', 'inline-function']]
105+
options: [
106+
['inline', 'inline-function'],
107+
{ allowInlineFuncSingleArg: true }
108+
]
91109
}
92110
],
93111
invalid: [
@@ -208,6 +226,30 @@ tester.run('v-on-handler-style', rule, {
208226
}
209227
]
210228
},
229+
{
230+
filename: 'test.vue',
231+
code: `<template>
232+
<div @click="() => foo()" />
233+
<div @click="(event) => foo(event)" />
234+
</template>`,
235+
output: `<template>
236+
<div @click="foo" />
237+
<div @click="foo" />
238+
</template>`,
239+
options: [['method', 'inline-function']],
240+
errors: [
241+
{
242+
message: 'Prefer method handler over inline function in v-on.',
243+
line: 2,
244+
column: 22
245+
},
246+
{
247+
message: 'Prefer method handler over inline function in v-on.',
248+
line: 3,
249+
column: 22
250+
}
251+
]
252+
},
211253
{
212254
filename: 'test.vue',
213255
code: `<template>
@@ -1162,20 +1204,84 @@ tester.run('v-on-handler-style', rule, {
11621204
<button @click="foo" />
11631205
<button @click="() => foo()" />
11641206
<button @click="() => foo($event)" />
1207+
<button @click="(event) => foo(event)" />
1208+
<template v-for="e in list">
1209+
<button @click="(event) => foo(event, e)" />
1210+
</template>
1211+
</template>`,
1212+
output: `<template>
1213+
<button @click="value++" />
1214+
<button @click="foo" />
1215+
<button @click="foo()" />
1216+
<button @click="foo($event)" />
1217+
<button @click="(event) => foo(event)" />
1218+
<template v-for="e in list">
1219+
<button @click="(event) => foo(event, e)" />
1220+
</template>
1221+
</template>`,
1222+
options: [['inline', 'inline-function']],
1223+
errors: [
1224+
{
1225+
message: 'Prefer inline handler over inline function in v-on.',
1226+
line: 2,
1227+
column: 25
1228+
},
1229+
{
1230+
message: 'Prefer inline handler over method handler in v-on.',
1231+
line: 3,
1232+
column: 25
1233+
},
1234+
{
1235+
message: 'Prefer inline handler over inline function in v-on.',
1236+
line: 4,
1237+
column: 25
1238+
},
1239+
{
1240+
message: 'Prefer inline handler over inline function in v-on.',
1241+
line: 5,
1242+
column: 25
1243+
},
1244+
{
1245+
message: 'Prefer inline handler over inline function in v-on.',
1246+
line: 6,
1247+
column: 25
1248+
},
1249+
{
1250+
message: 'Prefer inline handler over inline function in v-on.',
1251+
line: 8,
1252+
column: 27
1253+
}
1254+
]
1255+
},
1256+
// ['inline', 'inline-function'] + allowInlineFuncSingleArg
1257+
{
1258+
filename: 'test.vue',
1259+
code: `<template>
1260+
<button @click="() => value++" />
1261+
<button @click="foo" />
1262+
<button @click="() => foo()" />
1263+
<button @click="() => foo($event)" />
1264+
<button @click="(event) => foo(event)" />
11651265
<template v-for="e in list">
11661266
<button @click="() => foo(e)" />
1267+
<button @click="(event) => foo(event, e)" />
11671268
</template>
11681269
</template>`,
11691270
output: `<template>
11701271
<button @click="value++" />
11711272
<button @click="foo" />
11721273
<button @click="foo()" />
11731274
<button @click="foo($event)" />
1275+
<button @click="(event) => foo(event)" />
11741276
<template v-for="e in list">
11751277
<button @click="foo(e)" />
1278+
<button @click="(event) => foo(event, e)" />
11761279
</template>
11771280
</template>`,
1178-
options: [['inline', 'inline-function']],
1281+
options: [
1282+
['inline', 'inline-function'],
1283+
{ allowInlineFuncSingleArg: true }
1284+
],
11791285
errors: [
11801286
{
11811287
message: 'Prefer inline handler over inline function in v-on.',
@@ -1199,10 +1305,33 @@ tester.run('v-on-handler-style', rule, {
11991305
},
12001306
{
12011307
message: 'Prefer inline handler over inline function in v-on.',
1202-
line: 7,
1308+
line: 8,
12031309
column: 27
12041310
}
12051311
]
1312+
},
1313+
// ['method', 'inline-function'] + allowInlineFuncSingleArg
1314+
{
1315+
filename: 'test.vue',
1316+
code: `<template>
1317+
<div @click="() => foo()" />
1318+
<div @click="(event) => foo(event)" />
1319+
</template>`,
1320+
output: `<template>
1321+
<div @click="foo" />
1322+
<div @click="(event) => foo(event)" />
1323+
</template>`,
1324+
options: [
1325+
['method', 'inline-function'],
1326+
{ allowInlineFuncSingleArg: true }
1327+
],
1328+
errors: [
1329+
{
1330+
message: 'Prefer method handler over inline function in v-on.',
1331+
line: 2,
1332+
column: 22
1333+
}
1334+
]
12061335
}
12071336
]
12081337
})

0 commit comments

Comments
 (0)
Please sign in to comment.