自己做个小项目练手, 需要用到组件递归, 网上查了一些资料, 每个代码片段都认识, 但是连起来, 就一团浆糊.
既然人傻就多思考吧. 不明白的点有以下:
1. 组件怎么自己调用自己, 函数的递归是就是在 function fn(){ fn() }, 组件的递归没有看到这样子的呀.
答: 组件中使用 name 属性, 给组件自己定义个名字, 这样在组件中就可以自己调用自己了. 就像在函数中直接调用函数名来来递归.
2. 组件的递归中一层又一层数据是如何获取到的?
答: 将嵌套的数据重新赋值给 prop 设置的属性.
<tree-menu v-for="(item,index) in model.children" v-bind:model="item" v-bind:key="index"></tree-menu>
3. 组件递归是怎么结束的?
判断数据中是否存在属性, 以及该属性的值不为空. 见下面代码中的 haschild 方法.
- hasChild(){
- return this.model.children && this.model.children.length
- }
下面的代码来自 https://www.jianshu.com/p/84eb67487113
准备数据文件 --testdata.JS
- var demoData = [
- {
- 'id': '1',
- 'menuName': '基础管理',
- 'menuCode': '10',
- 'children': [
- {
- 'menuName': '用户管理',
- 'menuCode': '11'
- },
- {
- 'menuName': '角色管理',
- 'menuCode': '12',
- 'children': [
- {
- 'menuName': '管理员',
- 'menuCode': '121'
- },
- {
- 'menuName': 'CEO',
- 'menuCode': '122'
- },
- {
- 'menuName': 'CFO',
- 'menuCode': '123'
- },
- {
- 'menuName': 'COO',
- 'menuCode': '124'
- },
- {
- 'menuName': '普通人',
- 'menuCode': '124'
- }
- ]
- },
- {
- 'menuName': '权限管理',
- 'menuCode': '13'
- }
- ]
- },
- {
- 'id': '2',
- 'menuName': '商品管理',
- 'menuCode': ''
- },
- {
- 'id': '3',
- 'menuName': '订单管理',
- 'menuCode': '30',
- 'children': [
- {
- 'menuName': '订单列表',
- 'menuCode': '31'
- },
- {
- 'menuName': '退货列表',
- 'menuCode': '32',
- 'children': []
- }
- ]
- },
- {
- 'id': '4',
- 'menuName': '商家管理',
- 'menuCode': '',
- 'children': []
- }
- ];
- export default demoData;
- View Code
父组件
- <template>
- <div class="tree-menu">
- <ul v-for="menuItem in theModel">
- // 使用子组件, 并将数据传给子组件的 model 属性上, 供子组件使用.
- <my-tree :model="menuItem"></my-tree>
- </ul>
- </div>
- </template>
- <script>
- import testData from './testdata';
- import myTree from './treeMenu';
- export default {
- //name 属性是组件的名字, 这样组件才能调用组件自己.
- name: "side-bar",
- components: {
- // 即 treeMenu 文件, 它在 side-bar 组件中的名字设置为了 myTree.
- myTree
- },
- data() {
- return {
- // 绑定数据供 v-for 循环使用.
- theModel: testData
- }
- }
- }
- </script>
子组件 treeMenu(树形组件, 递归)
- <template>
- <li>
- // 控制图标的显示
- <span @click="toggle">
- <i v-if="hasChild" class="icon" v-bind:class="[open ?'folder-open':'folder']"></i>
- <i v-if="!hasChild" class="icon file-text"></i>
- {{model.menuName}}
- </span>
- // 判断数据中是否有可遍历的子元素.
- <ul v-show="open" v-if="hasChild">
- // 如果有调用组件自己 (tree-menu), 获取下一层可以遍历的数据, 将下一层数据绑定到 model 作为 model 新的数据.
- //key 用来标识组件的唯一性, 避免重复渲染.
- <tree-menu v-for="(item,index) in model.children" v-bind:model="item" v-bind:key="index"></tree-menu>
- </ul>
- </li>
- </template>
- <script>
- export default {
- //name 属性定义组件名, 有了名字组件才可以调用自己.
- name: "treeMenu",
- props: ['model'],
- data(){
- return {
- open:false
- }
- },
- computed:{
- hasChild(){
- return this.model.children && this.model.children.length
- }
- },
- methods:{
- toggle(){
- if(this.hasChild){
- this.open = !this.open
- }
- }
- }
- }
- </script>
来源: http://www.bubuko.com/infodetail-2945448.html