eslint-plugin-vue icon indicating copy to clipboard operation
eslint-plugin-vue copied to clipboard

Discourage dynamic-component if it's toggling between 2~3 components

Open privatenumber opened this issue 1 year ago • 1 comments

Please describe what the rule should do: Discourage using a dynamic component when you can use a v-if/v-else for better readability & type hints.

When reading <component :is="componentType"> it doesn't give a lot of information to the reader (or static analyzer) so it feels like the component can be anything and increase mental burden when trying to understand what a component does.

If componentType is actually a toggle between 2, 3 components, I think a v-if/v-else would be preferable as it makes it clear what elements/components are used in the file.

What category should the rule belong to?

[ ] Enforces code style (layout) [ ] Warns about a potential error (problem) [x] Suggests an alternate way of doing something (suggestion) [ ] Other (please specify:)

Provide 2-3 code examples that this rule should warn about:

Composition API with inline computed:

<script setup>
const props = defineProps({
	isButton: Boolean,
});
</script>

<template>
	<component :is="isButton ? 'button' : 'a'">
		Text
	</component>
</template>

Options API with computed property:

<template>
	<component :is="componentType">
		Text
	</component>
</template>

<script>
export default {
	props: {
		isButton: Boolean
	},
	computed: {
		componentType() {
			return isButton ? 'button' : 'a'
		}
	}
}
</script>

Additional context

privatenumber avatar Aug 03 '24 04:08 privatenumber

Another example of code that can be prevented by this rule.

Obviously, the imported component shouldn't be anything particular like an icon... On the other hand, it might be a good idea to actually allow (or even enforce) such a technique if an imported component's path matches some regex like \.svg$ (should be configurable) because <my-icon></my-icon> is quite verbose and doesn't accept any props anyway.

<template>
  <component :is="MyIcon"></component>
</template>

<script setup lang="ts">
import MyIcon from './any-icon.svg';

...
</script>

andreww2012 avatar Aug 04 '24 10:08 andreww2012