Close read Vue official documentation series 🎉
What is a recursive component?
Same meaning as ordinary recursion. Component recursion is a component that calls itself, and Vue uses the component name in the template to implement component recursion.
Personal summary
When we recurse to a template, such as generating a tree, a good design would have each node in the tree recursively create a unique component instance corresponding to it. The advantage is that the state of each node can be maintained independently. On the other hand, if our recursive components do not distinguish whether the content needs recursion or not, but all of them are contained in one component, it will lead to multiple nodes in one component instance, which is not good for later expansion.
Generate a separate component for each node recursively so that the state of the node can be cached using computed properties.
Concrete example
Now, to design the structure of the recursive component, we will create two components:
root
: Root component of a recursive component, exposing the recursive component instance.folder
: node component of the recursive component, which is used to render as a file/folder.
The directory structure is as follows:
─ ─ Tree │ ├ ─ ─ mixins. Js # logic reuse │ ├ ─ ─ Tree. The vue # recursive components of root components │ ├ ─ ─ TreeFolder. Vue # of each node in the Tree structure componentsCopy the code
mixins.js
import Vue from "vue";
const getRandomStr = () = > Math.random().toString(16).slice(-10);
export default {
methods: {
addItem(item) {
item.children.push({ name: getRandomStr() })
},
addRootItem(item) {
item.push({ name: getRandomStr() })
},
makeFolder(item) {
if(! item.children) { Vue.set(item,'children'[]);this.addItem(item); }}}}Copy the code
Tree.vue
<template>
<ul class="tree">
<tree-folder
v-for="item in treeData"
:key="item.name"
:tree-item="item"
/>
<li class="add" @click="addRootItem(treeData)">+</li>
</ul>
</template>
<script>
import TreeFolder from "./TreeFolder.vue";
import TreeMixins from "./mixins";
export default {
name: "Tree".mixins: [TreeMixins],
components: {
TreeFolder,
},
props: {
treeData: {
type: Array.default: () = >[],}}};</script>
<style scoped>
.tree {
margin: 0;
width: 320px;
text-align: left;
}
</style>
Copy the code
TreeFolder.vue
<template>
<li @dblclick="makeFolder(treeItem)">
<div class="tree-folder">
<span> {{ treeItem.name }}</span>
<a v-show="isFolder" @click="toggle">[{{ isOpen ? "-" : "+" }}]</a>
</div>
<ul v-if="isFolder" class="tree-list" v-show="isOpen">
<tree-folder
v-for="item in treeItem.children"
:key="item.name"
:tree-item="item"
@add-item="addItem"
/>
<li class="add" @click="addItem(treeItem)">+</li>
</ul>
</li>
</template>
<script>
import TreeMixins from "./mixins";
export default {
name: "TreeItem".mixins: [TreeMixins],
props: {
treeItem: Object,},data() {
return {
isOpen: false}; },computed: {
isFolder() {
return this.treeItem.children && this.treeItem.children.length; }},methods: {
toggle() {
this.isOpen = !this.isOpen; ,}}};</script>
<style scoped>
.tree-list {
margin: 0;
width: 320px;
text-align: left;
}
</style>
Copy the code
Now, with this partition, the roots of the recursive components are managed by a separate Tree component. Each child node corresponds to a unique TreeFolder component.