Skip to content

递归组件

Tree.vue

javascript
<template>
  <div>
    <TreeNode
      class="tree"
      v-for="item in data"
      :key="item.id"
      :node="item"
    ></TreeNode>
  </div>
</template>

<script>
import TreeNode from "@/components/TreeNode.vue";
export default {
  props: {
    data: {
      type: Array,
      default: () => []
    }
  },
  components: { TreeNode }
};
</script>

<style lang="scss" scoped>
.tree {
  text-align: left;
}
</style>
<template>
  <div>
    <TreeNode
      class="tree"
      v-for="item in data"
      :key="item.id"
      :node="item"
    ></TreeNode>
  </div>
</template>

<script>
import TreeNode from "@/components/TreeNode.vue";
export default {
  props: {
    data: {
      type: Array,
      default: () => []
    }
  },
  components: { TreeNode }
};
</script>

<style lang="scss" scoped>
.tree {
  text-align: left;
}
</style>

TreeNode.vue

javascript
<template>
  <div>
    <div
      @click="toggle"
      :style="{paddingLeft}"
    >
      <label for="">{{node.text}}</label><span v-if="hasChild">{{open?"-":"+"}}</span>
    </div>
    <div
      v-if="hasChild"
      v-show="open"
    >
      <tree-node
        v-for="item in node.children"
        :node="item"
        :key="item.id"
        :level="level+1"
      ></tree-node>
    </div>
  </div>
</template>

<script>
export default {
  name: "tree-node",
  props: {
    node: {
      type: Object
    },
    level: {
      type: Number,
      default: 1
    }
  },
  data() {
    return {
      open: false
    };
  },
  computed: {
    hasChild() {
      return this.node.children && this.node.children.length > 0;
    },
    paddingLeft() {
      return this.level - 1 + "em";
    }
  },
  methods: {
    toggle() {
      if (this.hasChild) {
        this.open = !this.open;
      }
    }
  }
};
</script>
<template>
  <div>
    <div
      @click="toggle"
      :style="{paddingLeft}"
    >
      <label for="">{{node.text}}</label><span v-if="hasChild">{{open?"-":"+"}}</span>
    </div>
    <div
      v-if="hasChild"
      v-show="open"
    >
      <tree-node
        v-for="item in node.children"
        :node="item"
        :key="item.id"
        :level="level+1"
      ></tree-node>
    </div>
  </div>
</template>

<script>
export default {
  name: "tree-node",
  props: {
    node: {
      type: Object
    },
    level: {
      type: Number,
      default: 1
    }
  },
  data() {
    return {
      open: false
    };
  },
  computed: {
    hasChild() {
      return this.node.children && this.node.children.length > 0;
    },
    paddingLeft() {
      return this.level - 1 + "em";
    }
  },
  methods: {
    toggle() {
      if (this.hasChild) {
        this.open = !this.open;
      }
    }
  }
};
</script>

data

javascript
;[
  {
    id: '00',
    text: '中国',
    children: [
      {
        id: '01',
        text: '湖北',
        children: [
          {
            id: '0101',
            text: '武汉',
            children: [
              { id: '010101', text: '光谷' },
              { id: '010102', text: '江夏' },
            ],
          },
          {
            id: '0102',
            text: '宜昌',
            children: [
              {
                id: '010201',
                text: '远安',
                children: [{ id: '01020101', text: '河口' }],
              },
              { id: '010202', text: '当阳' },
            ],
          },
        ],
      },
      {
        id: '02',
        text: '上海',
        children: [
          { id: '0201', text: '黄埔' },
          {
            id: '0202',
            text: '长宁',
            children: [
              { id: '020101', text: '金钟路' },
              { id: '020202', text: '北新泾' },
            ],
          },
        ],
      },
      { id: '03', text: '北京' },
    ],
  },
]
;[
  {
    id: '00',
    text: '中国',
    children: [
      {
        id: '01',
        text: '湖北',
        children: [
          {
            id: '0101',
            text: '武汉',
            children: [
              { id: '010101', text: '光谷' },
              { id: '010102', text: '江夏' },
            ],
          },
          {
            id: '0102',
            text: '宜昌',
            children: [
              {
                id: '010201',
                text: '远安',
                children: [{ id: '01020101', text: '河口' }],
              },
              { id: '010202', text: '当阳' },
            ],
          },
        ],
      },
      {
        id: '02',
        text: '上海',
        children: [
          { id: '0201', text: '黄埔' },
          {
            id: '0202',
            text: '长宁',
            children: [
              { id: '020101', text: '金钟路' },
              { id: '020202', text: '北新泾' },
            ],
          },
        ],
      },
      { id: '03', text: '北京' },
    ],
  },
]