Skip to content

Commit

Permalink
fix(prefer-use-template-ref): add support for shallowRef
Browse files Browse the repository at this point in the history
  • Loading branch information
ntnyq committed Nov 15, 2024
1 parent 16c8778 commit 8f9ab8e
Show file tree
Hide file tree
Showing 3 changed files with 42 additions and 12 deletions.
18 changes: 11 additions & 7 deletions docs/rules/prefer-use-template-ref.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,31 +2,32 @@
pageClass: rule-details
sidebarDepth: 0
title: vue/prefer-use-template-ref
description: require using `useTemplateRef` instead of `ref` for template refs
description: require using `useTemplateRef` instead of `ref/shallowRef` for template refs
since: v9.31.0
---

# vue/prefer-use-template-ref

> require using `useTemplateRef` instead of `ref` for template refs
> require using `useTemplateRef` instead of `ref/shallowRef` for template refs
## :book: Rule Details

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

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

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

```vue
<template>
<button ref="submitRef">Submit</button>
<button ref="cancelRef">Cancel</button>
<button ref="closeRef">Close</button>
</template>
<script setup>
import { ref, useTemplateRef } from 'vue';
import { ref, shallowRef, useTemplateRef } from 'vue';
/* ✓ GOOD */
const submitRef = useTemplateRef('submitRef');
Expand All @@ -35,6 +36,7 @@ This rule enforces using the new `useTemplateRef` function instead of `ref` for
/* ✗ BAD */
const closeRef = ref();
const cancelRef = shallowRef();
</script>
```

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

```vue
<template>
<button :ref="ref => button = ref">Content</button>
<button :ref="ref => submitRef = ref">Submit</button>
<button :ref="ref => cancelRef = ref">Cancel</button>
</template>
<script setup>
import { ref } from 'vue';
import { ref, shallowRef } from 'vue';
/* ✓ GOOD */
const button = ref();
const submitRef = ref();
const cancelRef = shallowRef();
</script>
```

Expand Down
17 changes: 12 additions & 5 deletions lib/rules/prefer-use-template-ref.js
Original file line number Diff line number Diff line change
Expand Up @@ -8,8 +8,12 @@ const utils = require('../utils')

/** @param expression {Expression | null} */
function expressionIsRef(expression) {
// @ts-ignore
return expression?.callee?.name === 'ref'
return (
// @ts-ignore
expression?.callee?.name === 'ref' ||
// @ts-ignore
expression?.callee?.name === 'shallowRef'
)
}

/** @type {import("eslint").Rule.RuleModule} */
Expand All @@ -18,13 +22,13 @@ module.exports = {
type: 'suggestion',
docs: {
description:
'require using `useTemplateRef` instead of `ref` for template refs',
'require using `useTemplateRef` instead of `ref/shallowRef` for template refs',
categories: undefined,
url: 'https://eslint.vuejs.org/rules/prefer-use-template-ref.html'
},
schema: [],
messages: {
preferUseTemplateRef: "Replace 'ref' with 'useTemplateRef'."
preferUseTemplateRef: "Replace 'ref/shallowRef' with 'useTemplateRef'."
}
},
/** @param {RuleContext} context */
Expand All @@ -46,7 +50,10 @@ module.exports = {
context,
{
'VAttribute[directive=false]'(node) {
if (node.key.name === 'ref' && node.value?.value) {
if (
(node.key.name === 'ref' || node.key.name === 'shallowRef') &&
node.value?.value
) {
templateRefs.add(node.value.value)
}
}
Expand Down
19 changes: 19 additions & 0 deletions tests/lib/rules/prefer-use-template-ref.js
Original file line number Diff line number Diff line change
Expand Up @@ -318,6 +318,25 @@ tester.run('prefer-use-template-ref', rule, {
column: 28
}
]
},
{
filename: 'single-shallowRef.vue',
code: `
<template>
<div ref="root"/>
</template>
<script setup>
import { shallowRef } from 'vue';
const root = shallowRef();
</script>
`,
errors: [
{
messageId: 'preferUseTemplateRef',
line: 7,
column: 22
}
]
}
]
})

0 comments on commit 8f9ab8e

Please sign in to comment.