diff --git a/src/v2/guide/components.md b/src/v2/guide/components.md index 57518af238..3fbb3f8cbe 100644 --- a/src/v2/guide/components.md +++ b/src/v2/guide/components.md @@ -995,7 +995,7 @@ If your component isn't passed content via `slot` elements, you can even make it 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. -### Recursive Component +### Recursive Components Components can recursively invoke themselves in their own template. However, they can only do so with the `name` option: @@ -1020,6 +1020,48 @@ template: '
' 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`). +### Circular References Between Components + +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: + +``` html +

+ {{ folder.name }} + +

+``` + +Then a `tree-folder-contents` component with this template: + +``` html + +``` + +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. + +However, if you're requiring/importing components using a __module system__, e.g. via Webpack or Browserify, you'll get an error: + +``` +Failed to mount component: template or render function not defined. +``` + +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." + +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: + +``` js +beforeCreate: function () { + this.$options.components.TreeFolderContents = require('./tree-folder-contents.vue') +} +``` + +Problem solved! + ### Inline Templates 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.