Subscribe on changes!

Can we use a builtin tag to recurse self-reference component ?

avatar
Dec 16th 2020

What problem does this feature solve?

Now vue using filename to assert if need to recursive components themselves.

selfname is inferred from filename https://github.com/vuejs/vue-next/blob/64d4681e4b9d88e17cd1515014866d43d0424d14/packages/compiler-core/src/transforms/transformElement.ts#L266-L273

This way may has these pitfalls:

  1. Will cause some misunderstanding because it prevent user-need-component resolving like #2821
  2. Will break recurse when changing the filename without reading code.

If we use a builtin tag:

  1. The first pitfall will not appear because user cant register a component named a builtin tag
  2. Changing filename will no longer affect recurse because the recursively self-reference component mechanism is self-consistent.

What does the proposed API look like?

Use a builtin tag instead of filename assertion, tag name maybe:

  1. self
  2. _self
  3. more...

@yyx990803 @posva @edison1105

avatar
Dec 19th 2020

I would say in practice, naming a component the same in different folders is a bad practice (https://v3.vuejs.org/style-guide/#tightly-coupled-component-names-strongly-recommended and all the naming recommendations).

In Vue 2, we used to need a name on the recursive component. Not needing it anymore looks like an improvement but brings the mentioned problems. What I find problematic is that giving the outer component a name different that its filename does not prevent it to refer to itself on the template:

<template>
  <h1>OUTER COMPONENT</h1>
  <Foo />
</template>
<script>
import Foo from '../inner/Foo.vue'
export default {
  name: 'OuterFoo',
  components: { Foo },
}
</script>

<Foo/> will render this component infinitely

avatar
Feb 17th 2021

At the very least a console warning would be nice. This would be a very difficult bug to fix in a larger app.

avatar
Feb 26th 2021

ping @HcySunYang @posva @yyx990803

avatar
Feb 26th 2021

While it might be a bad practice to name multiple components with the same name, it can indeed be difficult to fix such issues with big codebases (took us some time to find this issue). And there may be valid use-cases to name components with the same name. E.g. having a views directory and a models directory without having to postfix each component filename with "...View" or "...Model" The directories should be enough to act as a namespace for the components.

avatar
Mar 24th 2021

Even with moderately sized code-base this suddenly popped up in a few places for us after trying vue/next. Webpack hot-reload took the initial blame, as it seemed the file itself was not being properly loaded (parent component being loaded in place of the child component with the same file-name).

For us, the use case was the self-contained components displayed as separate pages. For example, there is Privacy Policy dialog box under "components", and then there is Privacy Policy page, under "pages". Both file names make sense as just PrivacyPolicy.vue, yet including a "component" on the "page" causes unexpected recursion. The same applies to other simple "footer" pages like T&C, About, Contact.

avatar
Mar 25th 2021

@luwuer Can you draft an RFC? If you don't have time, I can do this instead

avatar
Mar 26th 2021

Since the inferred filename is actually causing breakage, I adjusted its priority in abd129d8 and it is now used as a fallback only when normal resolution fails.

The issue with adding another built-in tag is that it could technically be a breaking change. I think with the fix in abd129d8, it is no longer strictly necessary. If we do want something like that, <component self/> maybe a safer option here.