Can we use a builtin tag to recurse self-reference component ?
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:
- Will cause some misunderstanding because it prevent user-need-component resolving like #2821
- Will break recurse when changing the filename without reading code.
If we use a builtin tag:
- The first pitfall will not appear because user cant register a component named a builtin tag
- 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:
self
_self
- more...
@yyx990803 @posva @edison1105
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
At the very least a console warning would be nice. This would be a very difficult bug to fix in a larger app.
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.
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.
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.