Skip to content

Commit 9dd58ce

Browse files
scaccogattochrisvfritz
authored andcommitted
components' documentation update base on issue#4117 (vuejs#574)
* components' documentation update base on issue#4117 vuejs/vue#4117 * require paths in both components and lifecycle reference * set a name property since we are in a recursive context * Update component circular dependency explanation
1 parent a7b3b40 commit 9dd58ce

File tree

1 file changed

+43
-1
lines changed

1 file changed

+43
-1
lines changed

src/v2/guide/components.md

Lines changed: 43 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -995,7 +995,7 @@ If your component isn't passed content via `slot` elements, you can even make it
995995

996996
Again, this _only_ works within string templates, as self-closing custom elements are not valid HTML and your browser's native parser will not understand them.
997997

998-
### Recursive Component
998+
### Recursive Components
999999

10001000
Components can recursively invoke themselves in their own template. However, they can only do so with the `name` option:
10011001

@@ -1020,6 +1020,48 @@ template: '<div><stack-overflow></stack-overflow></div>'
10201020

10211021
A component like the above will result in a "max stack size exceeded" error, so make sure recursive invocation is conditional (i.e. uses a `v-if` that will eventually be `false`).
10221022

1023+
### Circular References Between Components
1024+
1025+
Let's say you're building a file directory tree, like in Finder or File Explorer. You might have a `tree-folder` component with this template:
1026+
1027+
``` html
1028+
<p>
1029+
<span>{{ folder.name }}</span>
1030+
<tree-folder-contents :children="folder.children"/>
1031+
</p>
1032+
```
1033+
1034+
Then a `tree-folder-contents` component with this template:
1035+
1036+
``` html
1037+
<ul>
1038+
<li v-for="child in children">
1039+
<tree-folder v-if="child.children" :folder="child"/>
1040+
<span v-else>{{ child.name }}</span>
1041+
</li>
1042+
</ul>
1043+
```
1044+
1045+
When you look closely, you'll see that these components will actually be each other's descendent _and_ ancestor in the render tree - a paradox! When registering components globally with `Vue.component`, this paradox is resolved for you automatically. If that's you, you can stop reading here.
1046+
1047+
However, if you're requiring/importing components using a __module system__, e.g. via Webpack or Browserify, you'll get an error:
1048+
1049+
```
1050+
Failed to mount component: template or render function not defined.
1051+
```
1052+
1053+
To explain what's happening, I'll call our components A and B. The module system sees that it needs A, but first A needs B, but B needs A, but A needs B, etc, etc. It's stuck in a loop, not knowing how to fully resolve either component without first resolving the other. To fix this, we need to give the module system a point at which it can say, "A needs B _eventually_, but there's no need to resolve B first."
1054+
1055+
In our case, I'll make that point the `tree-folder` component. We know the child that creates the paradox is the `tree-folder-contents` component, so we'll wait until the `beforeCreate` lifecycle hook to register it:
1056+
1057+
``` js
1058+
beforeCreate: function () {
1059+
this.$options.components.TreeFolderContents = require('./tree-folder-contents.vue')
1060+
}
1061+
```
1062+
1063+
Problem solved!
1064+
10231065
### Inline Templates
10241066

10251067
When the `inline-template` special attribute is present on a child component, the component will use its inner content as its template, rather than treating it as distributed content. This allows more flexible template-authoring.

0 commit comments

Comments
 (0)