VUE实践记录

vue横向组织结构图实现

2020-07-22  本文已影响0人  Year_h

实现效果图如下:


image.png

数据格式 tree

let  dataInfo = [
        {
          name: "root",
          value: "root",
          children: [
            {
              name: "child1",
              value: "一级1",
              children: [
                {
                  name: "child2",
                  value: "二级1",
                  children: []
                },
                {
                  name: "child2",
                  value: "二级2",
                  children: []
                }
              ]
            },
            {
              name: "child1",
              value: "一级2",
              children: [
                {
                  name: "child2",
                  value: "二级3",
                  children: [
                  ]
                }
              ]
            }
          ]
        }
      ]

实现代码 递归调用最小实现单元 组件NodeTree.vue

<!--
 * @Descripttion: 横向树实现demo
 * @version: 
 * @Author: year
--> 
<template>
  <div class="item-content" ref="cardItemDiv">
    <div class="info-card">
      <div class="card-item" v-for="(item, index) in data" :key="index">
        <span
          class="vertical-line"
          :style="computedHeight(item.height, data.length, index)"
          v-if="item.name !== 'root'"
        ></span>
        <span class="horizontal-line" v-if="item.name !== 'root'"></span>
        <div class="div-card">
          <div>{{item.value}}</div>
        </div>
        <span class="horizontal-line" v-if="item.children&&item.children.length !== 0"></span>
        <equip-list :data="item.children" v-if="item.children&&item.children.length !== 0"></equip-list>
      </div>
    </div>
  </div>
</template>

<script>
export default {
  name: "equipList",
  props: {
    data: Array
  },
  data() {
    return {
    };
  },
  methods: {
    computedHeight(pheight, length, index) {
      if (length == 1 || length == 0) {
        return {
          height: "0px",
          display: "none"
        };
      } else {
        let height = 0;
        let marginTop = 0;
        let marginB = 0;
        if (index == 0) {
          height = pheight / 2;
          marginTop = height;
          return {
            height: height + "px",
            "margin-top": marginTop + "px"
          };
        }
        if (index == length - 1) {
          height = pheight / 2;
          marginB = height;
          return {
            height: height + "px",
            "margin-bottom": marginB + "px"
          };
        } else {
          height = pheight;
          return {
            height: height + "px"
          };
        }
      }
    }
  },
  components: {},
  mounted() {
  }
};
</script>

<style lang='scss' scoped>
.item-content {
  height: 100%;
  width: 100%;
  display: flex;
  .vertical-line {
    display: inline-block;
    width: 2px;
    background: #eaeaea;
  }

  .card-item {
    display: flex;
    align-items: center;
    .horizontal-line {
      width: 40px;
      display: inline-block;
      height: 2px;
      background: #eaeaea;
    }
  }
}

.div-card {
  height: 77px;
  & > div {
    display: flex;
    justify-content: center;
    align-items: center;
    width: 220px;
    height: 67px;
    background: inherit;
    background-color: rgba(253, 253, 253, 1);
    border: none;
    border-radius: 4px;
    -moz-box-shadow: 1px 3px 5px rgba(0, 0, 0, 0.2);
    -webkit-box-shadow: 1px 3px 5px rgba(0, 0, 0, 0.2);
    box-shadow: 1px 3px 5px rgba(0, 0, 0, 0.2);
    color: #8d8d8e;
  }
}
</style>

父组件调用 Parent.vue

引入NodeTree.vue

<!--
 * @Descripttion: 横向组织架构图实现
 * @version: 
 * @Author: year

--> 
<template>
  <div class="shopping-table-info">
    <NodeTree :data="dataInfo" />
  </div>
</template>

<script>
import NodeTree from "./ShoppingEquipList";
export default {
  data() {
    return {
      dataInfo: []
    };
  },
  methods: {
    getDataInfo() {
      let dataInfo = [
        {
          name: "root",
          value: "root",
          children: [
            {
              name: "child1",
              value: "一级1",
              children: [
                {
                  name: "child2",
                  value: "二级1",
                  children: []
                },
                {
                  name: "child2",
                  value: "二级2",
                  children: []
                }
              ]
            },
            {
              name: "child1",
              value: "一级2",
              children: [
                {
                  name: "child2",
                  value: "二级3",
                  children: []
                }
              ]
            }
          ]
        }
      ];

      let fixedData = dataInfo.map(item => {
        return this.traveTree(item);
      });

      this.dataInfo = fixedData;
    },
    traveTree(nodeInfo) {
      let childrenInfo = nodeInfo.children;
      if (!childrenInfo || childrenInfo.length == 0) {
        nodeInfo.height = 77;
      } else {
        childrenInfo.map(item => {
          this.traveTree(item);
        });

        nodeInfo.height = childrenInfo.reduce((preV, n) => {
          return preV + n.height;
        }, 0);
      }
      return nodeInfo;
    }
  },
  components: {
    NodeTree
  },
  mounted() {
    this.getDataInfo();
  }
};
</script>



实现思路

抽取最小实现单元,然后循环递归即可


image.png

(1)左右两端水平线 实现:


image.png
 <span class="horizontal-line" v-if="item.name !== 'root'"></span>
<span class="horizontal-line"  v-if="item.children&&item.children.length !== 0"></span>

span标签画两条水平线,然后利用flex布局,居中布局即可。最小单元后面的水平线判断没有后代的时候 不显示即可
(2)连接后代的纵轴部分实现:


image.png

需要知道每个后代的高度,然后第一个后代的高度/2 + 中间所有后代的高度和+ 最后一个后代的高度/2 就是所需要纵轴的高度
高度的具体实现代码: 假设最后一层后代的高度为70
a.初始数据处理: 利用二叉树的 后序遍历方法先给每一个节点添加上高度属性

     traveTree(nodeInfo) {
      let childrenInfo = nodeInfo.children;
      if (!childrenInfo || childrenInfo.length == 0) {
        nodeInfo.height = 77;
      } else {
        childrenInfo.map(item => {
          this.traveTree(item);
        });

        nodeInfo.height = childrenInfo.reduce((preV, n) => {
          return preV + n.height;
        }, 0);
      }
      return nodeInfo;
    }

b.计算链接线高度

 computedHeight(pheight, length, index) {
      if (length == 1 || length == 0) {
        return {
          height: "0px",
          display: "none"
        };
      } else {
        let height = 0;
        let marginTop = 0;
        let marginB = 0;
        if (index == 0) {
          height = pheight / 2;
          marginTop = height;
          return {
            height: height + "px",
            "margin-top": marginTop + "px"
          };
        }
        if (index == length - 1) {
          height = pheight / 2;
          marginB = height;
          return {
            height: height + "px",
            "margin-bottom": marginB + "px"
          };
        } else {
          height = pheight;
          return {
            height: height + "px"
          };
        }
      }
    }
上一篇 下一篇

猜你喜欢

热点阅读