vue树状关系图 关系图谱 族谱关系列表(纯css)

话不多说,先看看实现效果,如果对你有用我相信你会继续看下去。(128行代码实现自定义树状图)

这里的每一个颜色的方块都可以自定义样式,代码也不难,如果你想学习一下怎么使用css画出这样的线条可以继续看下去

好了,上代码,废话不多说了

第一步:引入组件注册组件

import DemoZou from '@/components/DemoZou.vue'

components: {
   DemoZou
},

第二步:使用组件

<DemoZou :list="obj"></DemoZou>

第三步:数据格式,可以根据自己想要的格式继续添加数据

obj: [    //数据具有扩展性,根据你自己的数据定义变量,只要children和name不改变就行
  {
    name: '一1',
    children: [
      {
        name: '二1',
        children: [
          {
            name: '三1'
          },
          {
            name: '三2'
          },
          {
            name: '三3'
          }
        ]
      },
      {
        name: '二2',
        children: [
          {
            name: '三1'
          },
          {
            name: '三2'
          }
        ]
      }
    ]
  }
]

第三步:把一下代码复制到.vue的空文件里面(文件地址要跟第一步对应)

靠左

<template>
  <!-- 第一层 -->
  <div class="flex">
    <div
      v-for="(item, index) in obj"
      :class="{ heng: !(index == num - 1) && num }"
    >
      <div class="div" :class="{ xia: xia(item), shang: shang2 }">
        <!-- 可以写具体样式,都可以更改,如更改大小,需要定义一下下面的值 -->
        {
    
    { item.name }}
      </div>

      <!-- <div class="flex heng">
        <div>
          <div class="div shang xia">二1</div>

          <div class="flex heng">
            <div>
              <div class="div shang">三1</div>
            </div>
            <div>
              <div class="div shang">三2</div>
            </div>
          </div>
        </div>
        <div>
          <div class="div shang">二2</div>
        </div>
      </div> -->
      <DemoZou
        v-if="item.children"
        :list="item.children"
        shang2="false"
        :num="item.children.length"
      ></DemoZou>
    </div>
  </div>
</template>

<script>
export default {
  name: 'DemoZou',
  props: ['list', 'shang2', 'num'],
  data() {
    return {
      obj: [],
      // 上划线
      shang: true
    }
  },
  created() {
    // 有值才会进来
    if (this.list) {
      this.obj = this.list
      this.shang = this.shang2
    }
  },
  computed: {
    // 计算属性计算下线
    xia(item) {
      return (item) => {
        if(!item.children){
            return ''
        }
        return item.children ? 'xia' : ''
      }
    }
  }
}
</script>

<style scoped>
* {
  margin: 0;
  padding: 0;
}
.box {
  margin-left: 100px;
  margin-top: 100px;
}
.flex {
  display: flex;
}
.div {
  width: 50px;
  height: 50px;
  display: flex;
  background-color: aquamarine;
  /* 盒子距离 */
  margin-bottom: 50px;
  margin-right: 50px;
}
div {
  position: relative;
}
/* 下线条 */
.xia::after {
  content: '';
  width: 1px;
  /* 线条往下的高度 */
  height: 25px;
  bottom: -25px;
  position: absolute;
  left: 50%;
  transform: translateX(-50%);
  background-color: black;
}
/* 上线条 */
.shang::before {
  content: '';
  width: 1px;
  /* 线条往下的高度 */
  height: 25px;
  top: -25px;
  position: absolute;
  left: 50%;
  transform: translateX(-50%);
  background-color: black;
}
/* 横线条 */
.heng::after {
  content: '';
  /* 需要剪去盒子的大小和偏移量 */
  width: 100%;
  height: 1px;
  position: absolute;
  left: 25px;
  top: -25px;
  background-color: black;
}
</style>

居中

<template>
  <!-- 第一层 -->
  <div class="flex">
    <div
      v-for="(item, index) in obj"
      :class="{ heng: !(index == num - 1) && num, zou: index > 0 }"
    >
      <div class="div">
        <!-- 可以写具体样式,都可以更改,如更改大小,需要定义一下下面的值 -->
        <div class="div2" :class="{ xia: xia(item), shang: shang2 }">
          {
    
    { item.name }}
        </div>
      </div>

      <!-- <div class="flex heng">
        <div>
          <div class="div shang xia">二1</div>

          <div class="flex heng">
            <div>
              <div class="div shang">三1</div>
            </div>
            <div>
              <div class="div shang">三2</div>
            </div>
          </div>
        </div>
        <div>
          <div class="div shang">二2</div>
        </div>
      </div> -->
      <DemoZou
        v-if="item.children"
        :list="item.children"
        shang2="false"
        :num="item.children.length"
      ></DemoZou>
    </div>
  </div>
</template>

<script>
export default {
  name: 'DemoZou',
  props: ['list', 'shang2', 'num'],
  data() {
    return {
      obj: [],
      // 上划线
      shang: true
    }
  },
  created() {
    // 有值才会进来
    if (this.list) {
      this.obj = this.list
      this.shang = this.shang2
    }
  },
  computed: {
    // 计算属性计算下线
    xia(item) {
      return (item) => {
        if(!item.children){
            return ''
        }
        return item.children ? 'xia' : ''
      }
    }
  }
}
</script>

<style scoped>
* {
  margin: 0;
  padding: 0;
}
.box {
  margin-left: 100px;
  margin-top: 100px;
}
.flex {
  display: flex;
}
.div {
  width: 100px;
  height: 100px;
  display: flex;
  /* 盒子距离 */
  margin: 0 auto;
  /* margin-bottom: 50px;
  margin-right: 50px; */
}
.div2 {
  background-color: aquamarine;
  margin: 0 auto;
  position: absolute;
  left: 50%;
  transform: translateX(-50%);
}
div {
  position: relative;
}
/* 下线条 */
.xia::after {
  content: '';
  width: 1px;
  /* 线条往下的高度 */
  height: 54px;
  bottom: -54px;
  position: absolute;
  left: 50%;
  transform: translateX(-50%);
  background-color: black;
}
/* 上线条 */
.shang::before {
  content: '';
  width: 1px;
  /* 线条往下的高度 */
  height: 25px;
  top: -25px;
  position: absolute;
  left: 50%;
  transform: translateX(-50%);
  background-color: black;
}
/* 横线条 */
.heng::after {
  content: '';
  /* 需要剪去盒子的大小和偏移量 */
  width: 50%;
  height: 1px;
  position: absolute;
  left: 50%;
  top: -25px;
  background-color: black;
}
.zou::before {
  content: '';
  /* 需要剪去盒子的大小和偏移量 */
  width: 50%;
  height: 1px;
  position: absolute;
  left: 0;
  top: -25px;
  background-color: black;
}
</style>

猜你喜欢

转载自blog.csdn.net/weixin_50587417/article/details/129690958