算法学习中,递归和迭代是一对孪生兄弟。下面我们就用递归来完成vue中的组件递归。也将认识到组件的递归,实际上就是数据递归的外在形式。所以我们完成组件的递归,最重要的还是定义好可以递归的数据结构。Here we go.
下面我们在VueJS里创建一个递归树组件,完整的Demo请戳这里
树组件的结构可以想像成文件目录
+ 根目录
+ 目录A
+ 目录A1
+ 目录B
可以把文件目录理解成树(Tree
),目录就是树的节点(Node
)。树总是有一个根节点,从根节点上进行某一操作,找到子节点,重复同一操作,直到叶子节点(没有子节点的节点)。
下面我们用label
和children
来表示目录名和子目录:
const tree = {
label: '根目录',
children: [
{
label: '目录A',
children: [
// 叶子节点
{
label: '目录A1'
}
]
}, {
label: '目录B'
}
]
}
上面的tree
数据就是我们要创建的Tree
组件要传入的data
,然后TreeNode.vue
组件长下面这样,接收props
,渲染根节点:
<template>
<ul>
<node :node="treeData">node>
ul>
template>
<script>
import Node from './components/Node'
export default {
name: 'tree-node',
props: {
treeData: Object
},
components: {
Node
}
}
script>
复制代码
TreeNode
组件的主要目的还是创建一个根节点,同时引入treeData
。
一个node节点的结构长下面这样,必需要有一个label属性和可能的children。从数据结构上就可以看出递归的样子了,所以html上的递归归根到底还是数据的递归
{
"label": "",
"children": [
// begin 子节点
{
"label": "",
children: []
}
// end
]
}
Node.vue
的详解可以看到此组件的name
为node
,然后组件里面用到了node
自身,但是不需要在components里显式引用。 这就是组件递归的关键点了
<template>
<li >
<span>{{node.label}}span>
<ul v-if="node.children && node.children.length">
<node :node="node" v-for="(node, i) of node.children" :key="i">node>
ul>
li>
template>
<span class="hljs-keyword">export</span> <span class="hljs-keyword">default</span> {
<span class="hljs-attr">name</span>: <span class="hljs-string">"node"</span>,
<span class="hljs-attr">props</span>: {
<span class="hljs-attr">node</span>: <span class="hljs-built_in">Object</span>
},
<span class="hljs-attr">components</span>: {
<span class="hljs-comment">// 这里不需要引用node自身</span>
}
};
<span class="xml"><span class="hljs-tag"></<span class="hljs-name">script</span>></span></span>
<span class="copy-code-btn">复制代码</span></code></pre><h2 class="heading" data-id="heading-3">各自归位</h2>
<p>最后我们创建一个<code>App.vue</code>来传递上面定义好的<code>treeData</code>给<code>TreeNode.vue</code>组件,<code>App.vue</code>如下面所示:</p>
<pre><code class="hljs html copyable" lang="html"><span class="hljs-comment"><!-- App.vue --></span>
<span class="hljs-tag"><<span class="hljs-name">template</span>></span>
<span class="hljs-tag"><<span class="hljs-name">div</span> <span class="hljs-attr">id</span>=<span class="hljs-string">"app"</span>></span>
<span class="hljs-tag"><<span class="hljs-name">TreeNode</span> <span class="hljs-attr">:tree</span>=<span class="hljs-string">"treeData"</span>></span><span class="hljs-tag"></<span class="hljs-name">TreeNode</span>></span>
<span class="hljs-tag"></<span class="hljs-name">div</span>></span>
<span class="hljs-tag"></<span class="hljs-name">template</span>></span>
<span class="hljs-tag"><<span class="hljs-name">script</span>></span><span class="javascript">
<span class="hljs-keyword">import</span> TreeNode <span class="hljs-keyword">from</span> <span class="hljs-string">"./components/TreeNode"</span>;
<span class="hljs-keyword">export</span> <span class="hljs-keyword">default</span> {
<span class="hljs-attr">name</span>: <span class="hljs-string">"App"</span>,
<span class="hljs-attr">data</span>: <span class="hljs-function"><span class="hljs-params">()</span> =></span> ({
<span class="hljs-attr">treeData</span>: {
<span class="hljs-attr">label</span>: <span class="hljs-string">"A"</span>,
<span class="hljs-attr">children</span>: [
{
<span class="hljs-attr">label</span>: <span class="hljs-string">"A-1"</span>,
<span class="hljs-attr">children</span>: [
{
<span class="hljs-attr">label</span>: <span class="hljs-string">"A-1-1"</span>
},
{
<span class="hljs-attr">label</span>: <span class="hljs-string">"A-1-2"</span>
}
]
}
]
}
}),
<span class="hljs-attr">components</span>: {
TreeNode
}
};
</span><span class="hljs-tag"></<span class="hljs-name">script</span>></span>
<span class="copy-code-btn">复制代码</span></code></pre><h2 class="heading" data-id="heading-4">结语</h2>
<p>好好练习下吧,希望对你理解递归组件有帮助。</p>
</div> <div class="image-viewer-box" data-v-78c9b824=""><!----></div>