用vue开发一个树形菜单

2020-01-09  本文已影响0人  累累的

看一下效果

效果图

index.vue

创建ul 并且使用v-for循环 data是调用组件传过来的值

<template>
  <div>
    <ul v-for="(item, index) in data" :key="index">
      <tree-item :data="item"></tree-item>
    </ul>
  </div>
</template>

写一下子组件传给父组件的值的类型 data是必填的

props: {
  data: {
    type: [Object, Array],
    required: true
  }
}

treeItem.vue

创建li 并且使用v-for循环

<li>
  <span @click="toggle(data)">
    <span v-if="hasChild">{{ isOpen ? "-" : "+" }}</span>
    {{ data[text] }}
  </span>
</li>

toggle是切换显示隐藏的子级 hasChild判断是否还有子级,如果有子级则用+/-来显示打开或关闭状态

因为可能子级还会有子级,所以需要组件嵌套 所以在li里面嵌套一个ul

<ul v-show="isOpen" v-if="hasChild">
    <tree-item
      v-for="(item, index) in data[children]"
      :data="item"
      :key="index"
      :treeProps="treeProps"
    ></tree-item>
</ul>

因为使用了组件嵌套,则需要给该组件定一个名称

export default {
  name: "TreeItem",
  props: {
    data: {
      type: [Object, String],
      required: true
    }
  },
  data: {
    isOpen: false
  }
}

因为hasChild需要实时更新,所以试用了计算属性computed

computed: {
  // 判断当前级别是否还有children
  hasChild() {
    return (
      this.data[children] && this.data[children].length;
    );
  }
}

点击子菜单判断是否有children,有就展开

toggle(data) {
    if (this.hasChild) {
      this.isOpen = !this.isOpen;
      data.open = this.isOpen;
    }
}

然后简单的写一下样式

<style>
ul {
  list-style: none;
  padding-left: 20px;
}
li {
  color: #000;
}
li > span {
  cursor: pointer;
  font-size: 14px;
  line-height: 20px;
}
</style>

最后附上全部代码

index.vue

<template>
  <div>
    <ul v-for="(item, index) in data" :key="index">
      <tree-item :data="item"></tree-item>
    </ul>
  </div>
</template>

<script>
import treeItem from "./item";
export default {
  props: {
    data: {
      type: [Object, Array],
      required: true
    }
  },
  components: {
    treeItem
  }
};
</script>

item.vue

<template>
  <li>
    <span @click="toggle(data)">
      <span v-if="hasChild">{{ isOpen ? "-" : "+" }}</span>
      {{
        data[text]
      }}
    </span>
    <ul v-show="isOpen" v-if="hasChild">
      <tree-item
        v-for="(item, index) in data[children]"
        :data="item"
        :key="index"
        :treeProps="treeProps"
      ></tree-item>
    </ul>
  </li>
</template>

<script>
import { getTree, keyword } from "../../views/mapShow/PJKeyVideo/api/api";
export default {
  name: "TreeItem", //递归组件必须有name
  props: {
    data: {
      type: [Object, Array], //多个可能的类型
      required: true
    }
  },
  data() {
    return {
      isOpen: false
    };
  },
  computed: {
    // 判断当前级别是否还有children
    hasChild() {
      return (
        this.data[children] && this.data[children].length;
      );
    }
  },
  methods: {
    // 点击子菜单也要判断是否有children,有就展开
    toggle(data) {
      if (this.hasChild) {
        this.isOpen = !this.isOpen;
      }
    },
  }
};
</script>

<style>
ul {
  list-style: none;
  padding-left: 20px;
}
li {
  color: #000;
}
li > span {
  cursor: pointer;
  font-size: 14px;
  line-height: 20px;
}
</style>

数据格式

treeData: [
  {
    children: [
      {
        children: [
          {
            text: "沈阳市"
          },
          {
            text: "大连市"
          }
        ],
        text: "辽宁省"
      }
    ],
    text: "主控制中心"
  }
 ]
上一篇 下一篇

猜你喜欢

热点阅读