vue纯css实现动态鱼骨图组件,附图片示例

21 篇文章 1 订阅
21 篇文章 2 订阅

先看示例图片吧

可以指定鱼骨根数和鱼翅的数量,具体看代码就行,默认4根鱼骨5个鱼翅

<template>
  <div class="fishbone">
    <div class="content">
      <el-row type="flex" class="top-bone">
        <div class="item-bone" v-for="(item, index) in arrList" :key="index">
          <ul class="item-bone-children" v-if="index % 2 == 0">
            <div v-if="index % 2 == 0" class="textTop">{{ text }}</div>
            <li v-for="(ele, i) in item.left" class="children-item" :key="i">
              <div v-if="ele.title" class="title"> {{ ele.title }}</div>
              <div class="text" v-else>{{ ele.label }}</div>
            </li>
          </ul>
          <ul class="item-bone-children item-bone-children-right" v-if="index % 2 == 0">
            <li v-for="(ele, i) in item.right" class="children-item-right" :key="i">
              <div v-if="ele.title" class="title"> {{ ele.title }}</div>
              <div class="text" v-else>{{ ele.label }}</div>
            </li>
          </ul>
        </div>
      </el-row>
      <div class="center-line">
        <div class="textCenter">{{ text }}</div>
      </div>
      <el-row type="flex" class="bottom-bone">
        <div class="item-bone" v-for="(item, index) in arrList" :key="index">
          <ul class="item-bone-children" v-if="index % 2 != 0">
            <div v-if="index % 2 != 0" class="textBottom">{{ text }}</div>
            <li v-for="(ele, i) in item.left" :key="i" class="children-item1">
              <div v-if="ele.title" class="title">
                {{ ele.title }}
              </div>
              <div class="text" v-else>{{ ele.label }}</div>
            </li>
          </ul>
          <ul class="item-bone-children item-bone-children-right" v-if="index % 2 != 0">
            <li v-for="(ele, i) in item.right" :key="i" class="children-item2">
              <div v-if="ele.title" class="title">
                {{ ele.title }}
              </div>
              <div class="text" v-else>{{ ele.label }}</div>
            </li>
          </ul>
        </div>
      </el-row>
    </div>
  </div>
</template>
<script>
  export default {
    data() {
      return {
        text: '字',
        strip_num: 4, //根数
        wing_num: 5, //翅数
        arrList: [],
      };
    },
    mounted() {
      let arr = [];
      let gObj = {
        label: '',
        left: [],
        right: [],
      };
      let cObj = {
        label: '请输入文字',
      };
      let wing_num = parseInt(this.wing_num) ?? 2;
      let strip_num = parseInt(this.strip_num) ?? 5;
      for (let index = 0; index < wing_num; index++) {
        gObj.left.push(cObj);
        gObj.right.push(cObj);
      }
      for (let index = 0; index < strip_num; index++) {
        arr.push(gObj);
      }
      this.arrList = arr;
    },
    methods: {},
  };
</script>
<style lang="scss" scoped>
  .fishbone {
    min-height: 300px;
    height: 100%;
    position: relative;
    $bnoe-color: #002766;
    max-width: 650px;

    .textCenter {
      position: absolute;
      top: -12px;
      width: 25px;
      height: 25px;
      line-height: 25px;
      text-align: center;
      background: green;
      font-weight: bold;
      right: -29px;
    }

    .textBottom {
      position: absolute;
      bottom: -28px;
      width: 25px;
      height: 25px;
      line-height: 25px;
      text-align: center;
      background: green;
      font-weight: bold;
      right: -25px;
      transform: skewx(45deg);
    }
    .textTop {
      position: absolute;
      top: -28px;
      width: 25px;
      height: 25px;
      line-height: 25px;
      text-align: center;
      background: green;
      font-weight: bold;
      right: -25px;
      transform: skewx(-45deg);
    }

    .leftIcon {
      border: 6px solid transparent;
      border-right: 6px solid black;
    }
    .rightIcon {
      border: 6px solid transparent;
      border-left: 6px solid black;
    }

    .content {
      width: 100%;
      height: 100%;
      /* position: absolute;
      left: 50%;
      top: 50%;
      transform: translate(-50%, -50%); */
    }

    .center-line {
      /* position: absolute;
      left: 0;
      top: 50%;
      transform: translateY(50%); */
      position: relative;
      width: 100%;
      height: 1px;
      background-color: $bnoe-color;
      &:after {
        position: absolute;
        right: -6px;
        bottom: -5px;
        content: ' ';
        border: 5px solid transparent;
        border-left: 5px solid black !important;
      }
    }

    .top-bone,
    .bottom-bone {
      /* position: absolute;
      height: 50%;
      width: 100%;
      padding-right: 100px;
      left: 0; */

      .item-bone {
        position: relative;
        display: flex;
        margin: 0 5px;
        //float: left;
        //min-width: 150px;
        // width: 150px;
        //margin: 0 10px;
      }

      .item-bone-children-right {
        border: none !important;
        margin: 0 !important;
        padding: 0;
      }

      .bottom-children-item-right {
        position: relative;
        &:not(:last-child) {
          border-bottom: 1px solid $bnoe-color;
          &:after {
            position: absolute;
            left: -5px;
            bottom: -5px;
            content: ' ';
            border: 5px solid transparent;
            border-right: 5px solid black !important;
            transform: skewx(-45deg);
          }
        }
      }

      .children-item-right {
        position: relative;
        &:not(:last-child) {
          border-bottom: 1px solid $bnoe-color;
          &:after {
            position: absolute;
            left: -5px;
            bottom: -5px;
            content: ' ';
            border: 5px solid transparent;
            border-right: 5px solid black !important;
            transform: skewx(-45deg);
          }
        }
      }

      .children-item {
        position: relative;

        &:not(:last-child) {
          border-bottom: 1px solid $bnoe-color;
          &:after {
            position: absolute;
            right: -5px;
            bottom: -5px;
            content: ' ';
            border: 5px solid transparent;
            border-left: 5px solid black;
            transform: skewx(-45deg);
          }
        }
      }

      .item-bone-children {
        position: relative;
        height: 100%;
        border-right: 2px solid $bnoe-color;
        transform: skewX(45deg);
        margin: 0 10px;
        list-style-type: none;
        padding: 0;
        padding-right: 5px;

        .text {
          text-align: right;
          padding-right: 20px;
          transform: skewx(-45deg);
          font-size: 13px;
          width: 100%;
          line-height: 30px;
          white-space: nowrap;
          color: #434343;
        }

        .title {
          text-align: center;
          transform: skewX(-45deg);
          font-size: 16px;
          font-weight: bolder;
          line-height: 35px;
          color: #002766;
        }
      }
    }

    .bottom-bone {
      bottom: 0;

      .item-bone-children {
        position: relative;
        transform: skewX(-45deg);
        .text {
          transform: skewX(45deg);
        }

        .title {
          transform: skewX(45deg);
        }
        .children-item1 {
          position: relative;
          &:not(:last-child) {
            border-bottom: 1px solid $bnoe-color;
            &:after {
              position: absolute;
              right: -5px;
              bottom: -5px;
              content: ' ';
              border: 5px solid transparent;
              border-left: 5px solid black !important;
              transform: skewx(45deg);
            }
          }
        }

        .children-item2 {
          position: relative;
          &:not(:last-child) {
            border-bottom: 1px solid $bnoe-color;
            &:after {
              position: absolute;
              left: -7px;
              bottom: -5px;
              content: ' ';
              border: 5px solid transparent;
              border-right: 5px solid black !important;
              transform: skewx(45deg);
            }
          }
        }
      }
    }
  }
</style>

  • 3
    点赞
  • 11
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
Vue中可以使用动态组件和异步组件实现按需加载和优化性能。下面是两种方式的实现方法。 1. 动态组件 动态组件是通过使用`<component>`标签,并在`is`属性中指定组件名来实现的。动态组件可以在运行时动态绑定组件实现按需加载。 示例代码: ```html <template> <div> <button @click="toggleComponent">Toggle Component</button> <component :is="currentComponent"></component> </div> </template> <script> import ComponentA from './ComponentA.vue'; import ComponentB from './ComponentB.vue'; export default { components: { ComponentA, ComponentB, }, data() { return { currentComponent: 'ComponentA', }; }, methods: { toggleComponent() { this.currentComponent = this.currentComponent === 'ComponentA' ? 'ComponentB' : 'ComponentA'; }, }, }; </script> ``` 2. 异步组件 异步组件是通过使用`Vue.component()`方法来实现的。该方法接收一个函数作为参数,函数返回一个`Promise`对象,在`Promise`对象被解决时,将组件作为参数传递给`Vue.component()`方法。 示例代码: ```html <template> <div> <button @click="loadComponent">Load Component</button> <component v-if="currentComponent" :is="currentComponent"></component> </div> </template> <script> export default { data() { return { currentComponent: null, }; }, methods: { async loadComponent() { const { default: ComponentC } = await import('./ComponentC.vue'); this.currentComponent = ComponentC; }, }, }; </script> ``` 在上面的代码中,我们使用了ES6的动态导入语法来异步加载组件。这将返回一个`Promise`对象,我们可以使用`await`关键字来等待`Promise`对象被解决。在`Promise`对象被解决时,我们将组件作为参数传递给`currentComponent`,并将其渲染到页面上。

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值