递归组件的使用

1.封装简单的Menu组件

代码目录结构如下:

router.js:

import Home from "@/views/Home.vue";

export default [
  {
    path: "/",
    alias: "/home_page",
    name: "home", //加上name属性  命名路由
    component: Home,
    props: route => ({
      food: route.query.food
    }),
    beforeEnter: (to, from, next) => {
      // if (from.name === "about") alert("这是从about来的");
      // else alert("这不是从about来的");
      next();
    }
  },
  {
    path: '/menu_page',
    name: 'menu_page',
    component: () => import('@/views/menu-page.vue')
  },
  {
    path: "*",
    component: () => import("@/views/error_404.vue")
  }
];

menu-page.vue:

<template>
  <div class="menu-box">
    <a-menu>
      <a-menu-item>1111</a-menu-item>
      <a-menu-item>2222</a-menu-item>
      <a-submenu>
        <div slot="title">3333</div>
        <a-menu-item>3333-11</a-menu-item>
        <a-submenu>
          <div slot="title">3333-22</div>
          <a-menu-item>3333-22-11</a-menu-item>
          <a-menu-item>3333-22-22</a-menu-item>
        </a-submenu>
      </a-submenu>
    </a-menu>
  </div>
</template>
<script>
import menuComponents from "_c/menu";
const { AMenu, AMenuItem, ASubmenu } = menuComponents;
export default {
  name: "menu_page",
  components: {
    AMenu,
    AMenuItem,
    ASubmenu
  }
};
</script>
<style lang="less">
.menu-box {
   300px;
  height: 400px;
}
</style>

a-menu.vue:

<template>
  <div class="a-menu">
    <slot></slot>
  </div>
</template>

<script>
export default {
  name: "AMenu"
};
</script>

<style lang="less">
.a-menu {
  & * {
    list-style: none;
  }
  ul {
    padding: 0;
    margin: 0;
  }
}
</style>

a-menu-item.vue:

<template>
  <li class="a-menu-item">
    <slot></slot>
  </li>
</template>

<script>
export default {
  name: "AMenuItem"
};
</script>

<style lang="less">
.a-menu-item {
  background: rgb(90, 92, 104);
  color: #fff;
}
</style>

a-submenu.vue:

<template>
  <ul class="a-submenu">
    <div class="a-submenu-title" @click="handlerClick">
      <slot name="title"></slot>
      <span class="shrink-icon" :style="{transform:`rotateZ(${showChild ? 0 : 180}deg)`}">^</span>
    </div>
    <div v-show="showChild" class="a-submenu-child-box">
      <slot></slot>
    </div>
  </ul>
</template>
<script>
export default {
  name: "ASubmenu",
  data() {
    return {
      showChild: false
    };
  },
  methods: {
    handlerClick() {
      this.showChild = !this.showChild;
    }
  }
};
</script>

<style lang="less">
.a-submenu{
  background: rgb(33, 35, 39);
  &-title{
    color: #fff;
    position: relative;
    .shrink-icon{
      position:absolute;
      top:0;
      right: 10px;
    }
  }
  &-child-box{
    overflow: hidden;
    padding-left: 20px;
  }
  li{
    background: rgb(33, 35, 39);
  }
}
</style>

运行效果:

2.递归组件

在以上提到的简单Menu的基础上,继续封装一个Recursivemenu(递归组件):

ReSubmenu.vue:

<template>
  <a-submenu>
    <div slot="title">{{ parent.title }}</div>
    <template v-for="(item, i) in parent.children">
      <a-menu-item v-if="!item.children" :key="`menu_item_${index}_${i}`">{{ item.title }}</a-menu-item>
      <re-submenu v-else :key="`menu_item_${index}_${i}`" :parent="item"></re-submenu>
    </template>
  </a-submenu>
</template>
<script>
import menuComponents from '_c/menu'
const { AMenuItem, ASubmenu } = menuComponents
export default {
  name: 'ReSubmenu',
  components: {
    AMenuItem,
    ASubmenu
  },
  props: {
    parent: {
      type: Object,
      default: () => ({})
    },
    index: Number
  }
}
</script>

index.js:

import ReSubmenu from "./ReSubmenu.vue";
export default ReSubmenu;

menu-page.vue:

<template>
  <div class="menu-box">
    <a-menu>
      <template v-for="(item, index) in list">
        <a-menu-item v-if="!item.children" :key="`menu_item_${index}`">{{ item.title }}</a-menu-item>
        <re-submenu v-else :key="`menu_item_${index}`" :parent="item" :index="index"></re-submenu>
      </template>
    </a-menu>
  </div>
</template>
<script>
import menuComponents from "_c/menu";
import ReSubmenu from "_c/Recursivemenu";
const { AMenu, AMenuItem, ASubmenu } = menuComponents;
export default {
  name: "menu_page",
  components: {
    AMenu,
    AMenuItem,
    ASubmenu,
    ReSubmenu
  },
  data() {
    return {
      list: [
        {
          title: "1111"
        },
        {
          title: "2222"
        },
        {
          title: "3333",
          children: [
            {
              title: "3333-1"
            },
            {
              title: "3333-2",
              children: [
                {
                  title: "3333-2-1"
                },
                {
                  title: "3333-2-2"
                },
                {
                  title: "3333-2-3",
                  children: [
                    {
                      title: "3333-2-3-1"
                    },
                    {
                      title: "3333-2-3-2"
                    }
                  ]
                }
              ]
            }
          ]
        },
        {
          title: "4444"
        }
      ]
    };
  }
};
</script>
<style lang="less">
.menu-box {
   300px;
  height: 400px;
}
</style>

运行效果:

原文地址:https://www.cnblogs.com/qicao/p/10828584.html