大白板展示框

85 阅读1分钟

预览!

工具

  • vue
  • vue-cli3

代码

// whiteblock.vue

<script>
export default {
  name: 'Elementui',
  data() {
    return {
      activeValue: '',
      activeNode: null,
      currentNodes: [],
      data: {
        label: '1.惹我dsfewffffffff惹我dsfewffffffff惹我dsfewffffffff惹我dsfewffffffff',
        value: '1',
        level: 1,
        children: [
          {
            label: '1.1 sdfewf',
            value: '1.1',
            level: 2,
            children: [
              {
                label: '1.1.1 fewjfiweo',
                value: '1.1.1',
                level: 3
              }
            ]
          },
          {
            label: '1.2 惹我dsfewffffffff惹我dsfewffffffff惹我dsfewffffffff惹我dsfewffffffff',
            value: '1.2',
            level: 2,
            children: [
              {
                label: '1.2.1 fjdsofjeowijfoiewjofiewjiofjewiojfoiewjfiojodsjklfjoiewjfoiewfjdsofjeowijfoiewjofiewjiofjewiojfoiewjfiojodsjklfjoiewjfoiewfjdsofjeowijfoiewjofiewjiofjewiojfoiewjfiojodsjklfjoiewjfoiewfjdsofjeowijfoiewjofiewjiofjewiojfoiewjfiojodsjklfjoiewjfoiewfjdsofjeowijfoiewjofiewjiofjewiojfoiewjfiojodsjklfjoiewjfoiewfjdsofjeowijfoiewjofiewjiofjewiojfoiewjfiojodsjklfjoiewjfoiewfjdsofjeowijfoiewjofiewjiofjewiojfoiewjfiojodsjklfjoiewjfoiewfjdsofjeowijfoiewjofiewjiofjewiojfoiewjfiojodsjklfjoiewjfoiewfjdsofjeowijfoiewjofiewjiofjewiojfoiewjfiojodsjklfjoiewjfoiewfjdsofjeowijfoiewjofiewjiofjewiojfoiewjfiojodsjklfjoiewjfoiewfjdsofjeowijfoiewjofiewjiofjewiojfoiewjfiojodsjklfjoiewjfoiewfjdsofjeowijfoiewjofiewjiofjewiojfoiewjfiojodsjklfjoiewjfoiew',
                value: '1.2.1',
                level: 3,
                children: [
                  {
                    label:
                      '1.2.1.1 fjdsofjeowijfoiewjofiewjiofjewiojfoiewjfiojodsjklfjoiewjfoiewfjdsofjeowijfoiewjofiewjiofjewiojfoiewjfiojodsjklfjoiewjfoiewfjdsofjeowijfoiewjofiewjiofjewiojfoiewjfiojodsjklfjoiewjfoiewfjdsofjeowijfoiewjofiewjiofjewiojfoiewjfiojodsjklfjoiewjfoiewfjdsofjeowijfoiewjofiewjiofjewiojfoiewjfiojodsjklfjoiewjfoiew',
                    value: '1.2.1.1',
                    level: 4,
                    children: [
                      {
                        label:
                          '1.2.1.1.1 fjdsofjeowijfoiewjofiewjiofjewiojfoiewjfiojodsjklfjoiewjfoiewfjdsofjeowijfoiewjofiewjiofjewiojfoiewjfiojodsjklfjoiewjfoiewfjdsofjeowijfoiewjofiewjiofjewiojfoiewjfiojodsjklfjoiewjfoiewfjdsofjeowijfoiewjofiewjiofjewiojfoiewjfiojodsjklfjoiewjfoiewfjdsofjeowijfoiewjofiewjiofjewiojfoiewjfiojodsjklfjoiewjfoiew',
                        value: '1.2.1.1.1',
                        level: 5
                      }
                    ]
                  }
                ]
              },
              {
                label: '1.2.2 ffewfwe',
                value: '1.2.2',
                level: 3,
              },
            ]
          }
        ]
      }
    }
  },

  methods: {
    renderChildren(data) {
      let arrowEle = item => (
        <i class={`el-icon-arrow-${item.active ? 'left' : 'right'}`} />
      )
      let children = data.map((item, index) => (
        <div
          class={[            'wb-item_cell',            item.active && (item.level === 1 ? 'indexActive' : 'active')          ]}
          key={item.value}
          on-click={() => this.handleCell(item)}
        >
          {this.hasChild(item) ? arrowEle(item) : ''}
          <span>{item.label}</span>
        </div>
      ))
      return children
    },

    cancelSiblingsActive(node) {
      // 取消兄弟元素 active 状态
      this.currentNodes.forEach(item => {
        item.forEach(n => {
          if (n.level < node.level) return
          if (n.value !== node.value) n.active = false
        })
      })
      // 删除兄弟元素的子后代
      this.currentNodes.splice(node.level)
    },

    addNode(node) {
      if (this.hasChild(node)) {
        node.active = true
        this.currentNodes.push(node.children)
      }
    },

    resetChildStatus(node) {
      let { currentNodes } = this
      if (currentNodes[node.level+1]) {
        currentNodes.forEach((list, index) => {
          if (index >= node.level) {
            list.forEach(l => {
              l.active = false
            })
          }
        })
        currentNodes.splice(node.level+1)
      }
    },

    handleCell(node) {

      if (node.active) {
        this.resetChildStatus(node)
        return
      }

      this.cancelSiblingsActive(node)
      this.addNode(node)
    },

    hasChild(data) {
      let hasProperty = data.hasOwnProperty('children')
      return hasProperty && data.children.length
    },

    hasActive(data) {
      return data.some(node => node.active)
    },

    getTranslate(index) {

      let offset = 0
      let curNodesLen = this.currentNodes.length
      let secondNodeOffsets = [ 70, 80, 85 ]
      let level = index + 1

      if (curNodesLen > 2 && index > 0) {
        let baseOffset = level > 2 ? (level - 2) * 100 : 0
        if (level == 2) offset = secondNodeOffsets[curNodesLen-3]
        if (level > 2 && level < curNodesLen) {
          offset = baseOffset + (secondNodeOffsets[curNodesLen-3] - (level - 2) * 15)
        }
        if (curNodesLen === level) {
          offset = baseOffset
        }
      }

      if (curNodesLen === 2 && index === 1) offset = 0

      return offset
    },

    renderContent() {

      return this.currentNodes.map((node, index) => {
        let offset = this.getTranslate(index)
        const parNode = (
          <div class="wb-item" key={index} style={{transform: `translateX(-${offset}%)`}}>
            {this.renderChildren(node)}
          </div>
        )
        return parNode
      })
    }
  },

  created() {
    this.currentNodes = [[this.data]]
  },

  render(h) {
    return <div class="whiteBlock">
    {this.renderContent()}
    </div>
  }
}
</script>
<style lang="less" scoped>
@theme: #f16a00;
div {
  box-sizing: border-box;
}
.whiteBlock {
  box-shadow: 0px 0px 20px 2px rgba(0, 0, 0, 0.1);
  overflow: hidden;
    position: relative;
    width: 100%;
    display: flex;
    text-align: left;
    font-weight: bold;
    // background-color: #f5f5f5;
  .wb-item {
    display: flex;
    flex-wrap: wrap;
    width: 50%;
    flex: 1 0 auto;
    background: #fff;
    box-shadow: -7px 0px 20px -4px rgba(0,0,0,0.1); 
    cursor: pointer;
    transition: all 0.2s;
  }
  .wb-item_cell {
    display: flex;
    align-items: center;
    word-break: break-all;
    width: 100%;
    padding: 20px;
    border-left: 4px solid transparent;
    span {
      flex: 1;
    }
  }
  .wb-item_cell.active {
    border-left: 4px solid @theme;
    color: @theme;
  }
  .wb-item_cell.indexActive {
    color: @theme;
  }
}

</style>