Vue Js中的树视图动态绝对元素(顶部,左侧)

时间:2018-05-14 15:01:22

标签: vuejs2

我想像这样制作Treeview:

         Qtr1     Qtr2     Qtr3     Qtr4
2015          81065.00 53990.69 41969.31
2016 41775.00   

我有来自API的数据:(ID,Root,Attribute,Depth)

A 
|--B
|  |--BC1
|  |   |--BC1-S
|  |      |--BC1-1
|  |      |--BC1-2
|  |__BC2
|      |--BC2-S
|         |--BC2-1
|         |--BC2-2
|--G
   |--GC1
       |--GC1-S1
       |  |--GC1-1
       |  |--GC1-2
       |
       |--GC1-S2
          |--GC1-3
          |--GC1-4

模板:

datas: [ 
  [1,  0,  'A',     0],
  [2,  1,  'B',     1], 
  [3,  2,  'BC1',   2],
  [4,  3,  'BC1-S', 3],
  [5,  4,  'BC1-1', 4],
  [6,  4,  'BC1-2', 4],
  [7,  2,  'BC2',   2],
  [8,  7,  'BC2-S', 3],
  [9,  8,  'BC2-1', 4],
  [10, 8,  'BC2-2', 4],
  [11, 1,  'G',     1],
  [12, 11, 'GC1',   2],
  [13, 12, 'GC1-S1',3],
  [14, 13, 'GC1-1', 4],
  [15, 13, 'GC1-2', 4],
  [16, 11, 'GC1-S2',3],
  [17, 16, 'GC1-3', 4],
  [18, 16, 'GC1-4', 4]
]

CSS:

<tr v-for="data in datas" :key="data[0]">
<td>
  <div v-if="data[3] == 0" class="tt tt-parent" style="left: 0px;">
    <div class="content">{{ data[2] }}</div>
  </div>

  <div v-else-if="data[3] == 1" class="tt tt-parent" style="left: 47px;">
    <div class="tail" style="height: 26px; width: 47px; left: -23.5px;"></div>
    <div class="content">{{ data[2] }}</div>
  </div>

  <div v-else-if="data[3] == 2" class="tt tt-parent" style="left: 95px;">
    <div class="tail" style="height: 26px; width: 47px; left: -23.5px;"></div>
    <div class="content">{{ data[2] }}</div>
  </div>

  <div v-else-if="data[3] == 3" class="tt tt-parent" style="left: 143px;">
    <div class="tail" style="height: 26px; width: 47px; left: -23.5px;"></div>
    <div class="content">{{ data[2] }}</div>
  </div>

  <div v-else-if="data[6] == 4" class="tt" style="left: 191px;">
    <div class="tail" style="height: 26px; width: 47px; left: -23.5px;"></div>
    <div class="content">{{ data[2] }}</div>
  </div>
</td> 
</tr>

大家好, 我想创建一个像这样的树视图。

  1. 问题是我无法连接A-G,B-BC2,GC1-GC1-S2之间的线路。
  2. 如何创建动态脚本,尤其是当数据超过50
  3. This is one of the failed examples:

1 个答案:

答案 0 :(得分:1)

首先,您需要将data构建为父子关系(使用内部java脚本函数将数组数据修改为父子对象或在服务器上修改它)

然后您可以使用如下的递归渲染。

// modified data from array
var data = {
  id: 1,
  name: 'A',
  open: true,  // default open
  children: [{
      name: 'B',
      children: [{
        name: 'BC1',
        children: [{
          name: 'BC1-S',
          children: [{
              name: 'BC1-1'
            },
            {
              name: 'BC1-2'
            }
          ]
        }]
      },{
        name: 'BC2',
        children: [{
          name: 'BC2-S',
          children: [{
              name: 'BC2-1'
            },
            {
              name: 'BC2-2'
            }
          ]
        }]
      }]
    },
    {
      name: 'G',
      children: [{
        name: 'GC1',
        children: [{
          name: 'GC1-S1',
          children: [{
              name: 'GC1-1'
            },
            {
              name: 'GC1-2'
            }
          ]
        },{
          name: 'GC1-S2',
          children: [{
              name: 'GC1-3'
            },
            {
              name: 'GC1-4'
            }
          ]
        }]
      }]
    }
  ]
}

// define the item component
Vue.component('item', {
  template: '#item-template',
  props: {
    model: Object
  },
  data: function() {
    return {
      open: this.model.open
    }
  },
  computed: {
    isFolder: function() {
      return this.model.children &&
        this.model.children.length
    }
  },
  methods: {
    toggle: function() {
      if (this.isFolder) {
        this.open = !this.open
      }
    }
  }
})

new Vue({
  el: '#main',
  data: {
    treeData: data
  }
})
body {
  font-family: Menlo, Consolas, monospace;
  color: #444;
}

.tree-view {}

.tree-view>ul {
  padding-left: 16px;
}

.tree-view li {
  list-style-type: none;
  margin: 0;
  padding: 10px 5px 0;
  position: relative;
}

.tree-view li:last-child {
  margin-bottom: 10px;
}

.tree-view li::after,
.tree-view li::before {
  content: '';
  left: -30px;
  position: absolute;
  right: auto;
}

.tree-view li::before {
  border-left: 1px solid #405567;
  height: calc(100% + 10px);
  top: 0;
  width: 1px;
}

.tree-view li::after {
  border-top: 1px solid #405567;
  height: 20px;
  top: 20px;
  width: 35px;
}

.tree-view .item {
  border: 1px solid #405567;
  border-radius: 2px;
  background-color: #fff;
  display: inline-block;
  padding: 2px 6px;
  text-decoration: none;
  cursor: pointer;
  box-shadow: 0 1px 4px rgba(0, 0, 0, 0.2);
}

.tree-view .folder {
  background-color: #fbf897;
}

.tree-view>ul>li::after,
.tree-view>ul>li::before {
  border: 0;
}

.tree-view li:last-child::before {
  height: 20px;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/vue/2.5.16/vue.min.js"></script>

<script type="text/x-template" id="item-template">
  <li>
    <div class="item" :class="{folder: isFolder}" @click="toggle">
      <span v-if="isFolder">{{ open ? '-' : '+' }}</span> {{ model.name }}
    </div>
    <ul v-show="open" v-if="isFolder">
      <item v-for="(model, index) in model.children" :key="index" :model="model">
      </item>
    </ul>
  </li>
</script>

<div class="tree-view" id="main">
  <ul>
    <item :model="treeData">
    </item>
  </ul>
</div>