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 && !item.children.length){
            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 && !item.children.length){
            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>

  • 5
    点赞
  • 13
    收藏
    觉得还不错? 一键收藏
  • 5
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 5
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值