Skip to content

Commit e95c657

Browse files
committed
feat(v-on-handler-style): add allowInlineFuncSingleArg option
1 parent 769b09f commit e95c657

File tree

3 files changed

+256
-46
lines changed

3 files changed

+256
-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

+87-42
Original file line numberDiff line numberDiff line change
@@ -5,12 +5,14 @@
55
'use strict'
66

77
const utils = require('../utils')
8+
const exp = require('node:constants')
89

910
/**
1011
* @typedef {import('eslint').ReportDescriptorFix} ReportDescriptorFix
1112
* @typedef {'method' | 'inline' | 'inline-function'} HandlerKind
1213
* @typedef {object} ObjectOption
1314
* @property {boolean} [ignoreIncludesComment]
15+
* @property {boolean} [allowInlineFuncSingleArg]
1416
*/
1517

1618
/**
@@ -33,8 +35,9 @@ function parseOptions(context) {
3335

3436
const option = options[1] || {}
3537
const ignoreIncludesComment = !!option.ignoreIncludesComment
38+
const allowInlineFuncSingleArg = option.allowInlineFuncSingleArg === true
3639

37-
return { allows, ignoreIncludesComment }
40+
return { allows, ignoreIncludesComment, allowInlineFuncSingleArg }
3841
}
3942

4043
/**
@@ -112,41 +115,73 @@ module.exports = {
112115
url: 'https://eslint.vuejs.org/rules/v-on-handler-style.html'
113116
},
114117
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-
}
118+
schema: {
119+
anyOf: [
120+
// `inline`, `inline-function` or `['method', 'inline']`
121+
{
122+
type: 'array',
123+
items: [
124+
{
125+
anyOf: [
126+
{ enum: ['inline', 'inline-function'] },
127+
{
128+
type: 'array',
129+
items: [{ const: 'method' }, { const: 'inline' }],
130+
uniqueItems: true,
131+
additionalItems: false,
132+
minItems: 2,
133+
maxItems: 2
134+
}
135+
]
136+
},
137+
{
138+
type: 'object',
139+
properties: {
140+
ignoreIncludesComment: {
141+
type: 'boolean'
142+
}
143+
},
144+
additionalProperties: false
145+
}
146+
],
147+
additionalItems: false,
148+
minItems: 1,
149+
maxItems: 2
146150
},
147-
additionalProperties: false
148-
}
149-
],
151+
// `['method', 'inline-function']` or `['inline', 'inline-function']`
152+
{
153+
type: 'array',
154+
items: [
155+
{
156+
type: 'array',
157+
items: [
158+
{ enum: ['method', 'inline'] },
159+
{ const: 'inline-function' }
160+
],
161+
uniqueItems: true,
162+
additionalItems: false,
163+
minItems: 2,
164+
maxItems: 2
165+
},
166+
{
167+
type: 'object',
168+
properties: {
169+
ignoreIncludesComment: {
170+
type: 'boolean'
171+
},
172+
allowInlineFuncSingleArg: {
173+
type: 'boolean'
174+
}
175+
},
176+
additionalProperties: false
177+
}
178+
],
179+
additionalItems: false,
180+
minItems: 0,
181+
maxItems: 2
182+
}
183+
]
184+
},
150185
messages: {
151186
preferMethodOverInline:
152187
'Prefer method handler over inline handler in v-on.',
@@ -170,7 +205,8 @@ module.exports = {
170205
},
171206
/** @param {RuleContext} context */
172207
create(context) {
173-
const { allows, ignoreIncludesComment } = parseOptions(context)
208+
const { allows, ignoreIncludesComment, allowInlineFuncSingleArg } =
209+
parseOptions(context)
174210

175211
/** @type {Set<VElement>} */
176212
const upperElements = new Set()
@@ -535,14 +571,23 @@ module.exports = {
535571
case 'ArrowFunctionExpression':
536572
case 'FunctionExpression': {
537573
// 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-
) {
574+
if (allows[0] === 'inline-function') {
544575
return
545576
}
577+
578+
if (allows[1] === 'inline-function') {
579+
if (expression.params.length > 1) {
580+
return
581+
}
582+
583+
if (
584+
expression.params.length === 1 &&
585+
allowInlineFuncSingleArg
586+
) {
587+
return
588+
}
589+
}
590+
546591
for (const allow of allows) {
547592
if (verifyForInlineFunction(expression, allow)) {
548593
return

0 commit comments

Comments
 (0)