Skip to content

Commit 4500389

Browse files
authored
fix(prefer-use-template-ref): add support for shallowRef (#2608)
1 parent 16c8778 commit 4500389

File tree

4 files changed

+65
-13
lines changed

4 files changed

+65
-13
lines changed

docs/rules/index.md

+1-1
Original file line numberDiff line numberDiff line change
@@ -270,7 +270,7 @@ For example:
270270
| [vue/prefer-prop-type-boolean-first](./prefer-prop-type-boolean-first.md) | enforce `Boolean` comes first in component prop types | :bulb: | :warning: |
271271
| [vue/prefer-separate-static-class](./prefer-separate-static-class.md) | require static class names in template to be in a separate `class` attribute | :wrench: | :hammer: |
272272
| [vue/prefer-true-attribute-shorthand](./prefer-true-attribute-shorthand.md) | require shorthand form attribute when `v-bind` value is `true` | :bulb: | :hammer: |
273-
| [vue/prefer-use-template-ref](./prefer-use-template-ref.md) | require using `useTemplateRef` instead of `ref` for template refs | | :hammer: |
273+
| [vue/prefer-use-template-ref](./prefer-use-template-ref.md) | require using `useTemplateRef` instead of `ref`/`shallowRef` for template refs | | :hammer: |
274274
| [vue/require-default-export](./require-default-export.md) | require components to be the default export | | :warning: |
275275
| [vue/require-direct-export](./require-direct-export.md) | require the component to be directly exported | | :hammer: |
276276
| [vue/require-emit-validator](./require-emit-validator.md) | require type definitions in emits | :bulb: | :hammer: |

docs/rules/prefer-use-template-ref.md

+11-7
Original file line numberDiff line numberDiff line change
@@ -2,31 +2,32 @@
22
pageClass: rule-details
33
sidebarDepth: 0
44
title: vue/prefer-use-template-ref
5-
description: require using `useTemplateRef` instead of `ref` for template refs
5+
description: require using `useTemplateRef` instead of `ref`/`shallowRef` for template refs
66
since: v9.31.0
77
---
88

99
# vue/prefer-use-template-ref
1010

11-
> require using `useTemplateRef` instead of `ref` for template refs
11+
> require using `useTemplateRef` instead of `ref`/`shallowRef` for template refs
1212
1313
## :book: Rule Details
1414

1515
Vue 3.5 introduced a new way of obtaining template refs via
1616
the [`useTemplateRef()`](https://vuejs.org/guide/essentials/template-refs.html#accessing-the-refs) API.
1717

18-
This rule enforces using the new `useTemplateRef` function instead of `ref` for template refs.
18+
This rule enforces using the new `useTemplateRef` function instead of `ref`/`shallowRef` for template refs.
1919

2020
<eslint-code-block :rules="{'vue/prefer-use-template-ref': ['error']}">
2121

2222
```vue
2323
<template>
2424
<button ref="submitRef">Submit</button>
25+
<button ref="cancelRef">Cancel</button>
2526
<button ref="closeRef">Close</button>
2627
</template>
2728
2829
<script setup>
29-
import { ref, useTemplateRef } from 'vue';
30+
import { ref, shallowRef, useTemplateRef } from 'vue';
3031
3132
/* ✓ GOOD */
3233
const submitRef = useTemplateRef('submitRef');
@@ -35,6 +36,7 @@ This rule enforces using the new `useTemplateRef` function instead of `ref` for
3536
3637
/* ✗ BAD */
3738
const closeRef = ref();
39+
const cancelRef = shallowRef();
3840
</script>
3941
```
4042

@@ -47,14 +49,16 @@ This rule skips `ref` template function refs as these should be used to allow cu
4749

4850
```vue
4951
<template>
50-
<button :ref="ref => button = ref">Content</button>
52+
<button :ref="ref => submitRef = ref">Submit</button>
53+
<button :ref="ref => cancelRef = ref">Cancel</button>
5154
</template>
5255
5356
<script setup>
54-
import { ref } from 'vue';
57+
import { ref, shallowRef } from 'vue';
5558
5659
/* ✓ GOOD */
57-
const button = ref();
60+
const submitRef = ref();
61+
const cancelRef = shallowRef();
5862
</script>
5963
```
6064

lib/rules/prefer-use-template-ref.js

+13-5
Original file line numberDiff line numberDiff line change
@@ -8,8 +8,12 @@ const utils = require('../utils')
88

99
/** @param expression {Expression | null} */
1010
function expressionIsRef(expression) {
11-
// @ts-ignore
12-
return expression?.callee?.name === 'ref'
11+
return (
12+
// @ts-ignore
13+
expression?.callee?.name === 'ref' ||
14+
// @ts-ignore
15+
expression?.callee?.name === 'shallowRef'
16+
)
1317
}
1418

1519
/** @type {import("eslint").Rule.RuleModule} */
@@ -18,13 +22,13 @@ module.exports = {
1822
type: 'suggestion',
1923
docs: {
2024
description:
21-
'require using `useTemplateRef` instead of `ref` for template refs',
25+
'require using `useTemplateRef` instead of `ref`/`shallowRef` for template refs',
2226
categories: undefined,
2327
url: 'https://eslint.vuejs.org/rules/prefer-use-template-ref.html'
2428
},
2529
schema: [],
2630
messages: {
27-
preferUseTemplateRef: "Replace 'ref' with 'useTemplateRef'."
31+
preferUseTemplateRef: "Replace '{{name}}' with 'useTemplateRef'."
2832
}
2933
},
3034
/** @param {RuleContext} context */
@@ -79,7 +83,11 @@ module.exports = {
7983

8084
context.report({
8185
node: scriptRef.node,
82-
messageId: 'preferUseTemplateRef'
86+
messageId: 'preferUseTemplateRef',
87+
data: {
88+
// @ts-ignore
89+
name: scriptRef.node?.callee?.name
90+
}
8391
})
8492
}
8593
}

tests/lib/rules/prefer-use-template-ref.js

+40
Original file line numberDiff line numberDiff line change
@@ -214,6 +214,9 @@ tester.run('prefer-use-template-ref', rule, {
214214
errors: [
215215
{
216216
messageId: 'preferUseTemplateRef',
217+
data: {
218+
name: 'ref'
219+
},
217220
line: 7,
218221
column: 22
219222
}
@@ -235,6 +238,9 @@ tester.run('prefer-use-template-ref', rule, {
235238
errors: [
236239
{
237240
messageId: 'preferUseTemplateRef',
241+
data: {
242+
name: 'ref'
243+
},
238244
line: 9,
239245
column: 22
240246
}
@@ -256,11 +262,17 @@ tester.run('prefer-use-template-ref', rule, {
256262
errors: [
257263
{
258264
messageId: 'preferUseTemplateRef',
265+
data: {
266+
name: 'ref'
267+
},
259268
line: 8,
260269
column: 25
261270
},
262271
{
263272
messageId: 'preferUseTemplateRef',
273+
data: {
274+
name: 'ref'
275+
},
264276
line: 9,
265277
column: 22
266278
}
@@ -288,6 +300,9 @@ tester.run('prefer-use-template-ref', rule, {
288300
errors: [
289301
{
290302
messageId: 'preferUseTemplateRef',
303+
data: {
304+
name: 'ref'
305+
},
291306
line: 14,
292307
column: 33
293308
}
@@ -314,10 +329,35 @@ tester.run('prefer-use-template-ref', rule, {
314329
errors: [
315330
{
316331
messageId: 'preferUseTemplateRef',
332+
data: {
333+
name: 'ref'
334+
},
317335
line: 12,
318336
column: 28
319337
}
320338
]
339+
},
340+
{
341+
filename: 'single-shallowRef.vue',
342+
code: `
343+
<template>
344+
<div ref="root"/>
345+
</template>
346+
<script setup>
347+
import { shallowRef } from 'vue';
348+
const root = shallowRef();
349+
</script>
350+
`,
351+
errors: [
352+
{
353+
messageId: 'preferUseTemplateRef',
354+
data: {
355+
name: 'shallowRef'
356+
},
357+
line: 7,
358+
column: 22
359+
}
360+
]
321361
}
322362
]
323363
})

0 commit comments

Comments
 (0)