使用vue组件递归自调用构成树形列表-tree

在这里插入图片描述

在vue 官方看到写的tree结构是组件自调用产生递归生成树形结构,然后我测试了一下将它利用在菜单上面了
parent组件
<template>
  <ul>
    <li id="demo" v-for="first in treeData">
      <tree-item class="item" :item="first" />
    </li>
  </ul>
</template>

<script>
import treeItem from "./treeItem";
const menu = [
  { id: 1, name: "首页",     pid: 0, icon: 'el-icon-s-home' },
  { id: 2, name: "内容创作", pid: 0, icon: 'el-icon-edit-outline' },
    { id: 21, name: "发表博文",     pid: 2, icon: 'el-icon-document' },
      { id: 221, name: "新闻",     pid: 21, icon: 'el-icon-star-off' },
    { id: 22, name: "上传资源",     pid: 2, icon: 'el-icon-document' },
    { id: 23, name: "上传视频",     pid: 2, icon: 'el-icon-document' },
    { id: 23, name: "发布问题",     pid: 2, icon: 'el-icon-document' },
  { id: 3, name: "内容管理", pid: 0, icon: 'el-icon-document' },
    { id: 31, name: "文章管理",   pid: 3, icon: 'el-icon-document' },
    { id: 32, name: "资源管理",   pid: 3, icon: 'el-icon-document' },
    { id: 33, name: "评论管理",   pid: 3, icon: 'el-icon-document' },
    { id: 34, name: "分类专栏",   pid: 3, icon: 'el-icon-document' },
    { id: 35, name: "视频管理",   pid: 3, icon: 'el-icon-document' },
    { id: 36, name: "自定义模块", pid: 3, icon: 'el-icon-document' },
    { id: 37, name: "订阅专栏",   pid: 3, icon: 'el-icon-document' },
    { id: 38, name: "问答管理",   pid: 3, icon: 'el-icon-document' },
  { id: 4, name: "数据观星", pid: 0, icon: 'el-icon-pie-chart' },
    { id: 41, name: "博文数据", pid: 4, icon: 'el-icon-document' },
    { id: 42, name: "下载数据", pid: 4, icon: 'el-icon-document' },
    { id: 43, name: "收益数据", pid: 4, icon: 'el-icon-document' },
    { id: 44, name: "粉丝数据", pid: 4, icon: 'el-icon-document' },
    { id: 45, name: "粉丝数据", pid: 4, icon: 'el-icon-document' },
    { id: 46, name: "一周小结", pid: 4, icon: 'el-icon-document' },
  { id: 5, name: "收益中心", pid: 0, icon: 'el-icon-coin' },
  { id: 6, name: "创作活动", pid: 0, icon: 'el-icon-ship' },
    { id: 61, name: "活动列表", pid: 6, icon: 'el-icon-document' },
    { id: 62, name: "投稿管理", pid: 6, icon: 'el-icon-document' },
  { id: 7, name: "工具",     pid: 0, icon: 'el-icon-setting' },
    { id: 71, name: "搬家",         pid: 7, icon: 'el-icon-document' },
    { id: 72, name: "博客打赏",     pid: 7, icon: 'el-icon-document' },
    { id: 73, name: "开头付费资源", pid: 7, icon: 'el-icon-document' },
  { id: 8, name: "创作权益", pid: 0, icon: 'el-icon-trophy' },
    { id: 81, name: "等级权益",   pid: 8, icon: 'el-icon-document' },
    { id: 82, name: "自定义域名", pid: 8, icon: 'el-icon-document' },
  { id: 9, name: "设置",     pid: 0, icon: 'el-icon-s-tools' },
    { id: 91, name: "博客设置",     pid: 9, icon: 'el-icon-document' },
];
export default {
  name: "tree",
  components: { treeItem },
  data() {
    return {
      treeData: []
    };
  },
  mounted() {
    this.treeData = this.__toTree(menu);
  },

  methods: {
    __toTree(data) {
      data.forEach(item => delete item.children);
      let map = {}, val = [];
      data.forEach(item => (map[item.id] = item));
      data.forEach((item, index) => {
        let parent = map[item.pid];
        if (parent) (parent.children || (parent.children = [])).push(item);
        else val.push(item);
      });
      return val;
    }
  }
  //  End
};
</script>
<style lang='stylus' scoped>
ul {
  padding-left: 1em;
  line-height: 1.5em;
  width: 200px;
  background-color: #409EFF;
  color: #fff;
}
</style>

children 组件
<template >
  <div :class="{'second-level': second, 'third-level': third}">
    <p @click="toggle">
      <b :class="item.icon"></b>
      {{ item.name }}
      <i v-if="isFolder" :class="icon"></i>
    </p>
    <ul v-show="isOpen" v-if="isFolder">
      <tree-item class="item" v-for="(child, index) in item.children" :key="index" :item="child" />
    </ul>
  </div>
</template>

<script>
export default {
  name: "treeItem",
  data() {
    return {
      isOpen: false
    };
  },
  props: ["item"],

  methods: {
    toggle() {
      if (this.isFolder) this.isOpen = !this.isOpen;
    }
  },
  computed: {
    isFolder() {
      return this.item.children && this.item.children.length;
    },
    icon() {
      return this.isOpen ? "el-icon-arrow-down" : "el-icon-arrow-right";
    },
    second() {
      return this.item.children && this.item.pid > 0;
    },
    third() {
      return !this.item.children && this.item.pid > 0;
    }
  }
  //  End
};
</script>

<style lang='css' scoped>
p {
  position: relative;
}
b {
  margin-right: 5px;
}
i {
  position: absolute;
  top: 2.5px;
  right: 20px;
}
.second-level, .third-level {
  margin-left: 10px;
}
</style>

</style>

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值