Bootstrap

dataV中重置边框组件的宽高的initWH方法的使用

先说下我遇到的情况,项目就是很经典的后台管理系统,菜单在左侧,并且可以收缩,首页是个可视化页面,用到了dataV边框组件,但是收缩菜单的时候问题出现了,边框无法自适应父容器,下面是效果图:

可以很明显的看出来,当我们收缩菜单的时候,中间的dataV边框并没有自适应容器,展开的时候又超出了容器的宽度,所以bug就来了,为了解决百度找了好多资料,但基本上都是说使用组件内部的initWH方法重置组件的宽高,官网也确实有说 

 

 但我加上就是不起作用!! 

干脆就直接找源码看下了,看能不能找到答案,这个边框组件其实是:最外层有个容器,然后里面svg画出来的线,然后还有跟svg同级一个div作为插槽,就是我们在边框组件内部写的内容,然后js代码部分确实有个initWH方法,先贴下源码: 

可以看到initWH方法中的 this.width 和 this.height 就是我们的svg对应的宽高,也就是我们没有自适应的宽高!然后就试着在initWH中打印看下这个 this.width  和  this.height 和 dom,从initWH方法中可以看出这个width和height其实 就是我们的父容器的宽高,打印出来之后发现dom的宽度(最外层的div就是类名位dv-border-box-8)已经变了,但是把dom.clientWidth和dom.clientHeight赋值给我们的this.width和this.height(就是我们的svg的宽高),发现赋上去的值还是改变之前的值!!这就奇怪了,后来换个思路,想了一下菜单展开收缩的时候是不是有一定的时间,但是多少时间我们控制不了,也不确定,所以是不是还没收缩展开完成我们就去拿dom元素的宽高赋值了,所以我在这加了个setTimeout 延迟5000再赋值:

initWH (resize = true) {
  console.log('触发 initWH----->>>')
  const { $nextTick, $refs, ref, onResize } = this

  return new Promise(resolve => {
    $nextTick(_ => {
      const dom = this.dom = $refs[ref]

      setTimeout(() => {
        this.width = dom ? dom.clientWidth : 0
        this.height = dom ? dom.clientHeight : 0
      }, 5000)

      if (!dom) {
        console.warn('DataV: Failed to get dom node, component rendering may be abnormal!')
      } else if (!this.width || !this.height) {
        console.warn('DataV: Component width or height is 0px, rendering abnormality may occur!')
      }

      if (typeof onResize === 'function' && resize) onResize()

      resolve()
    })
  })
},

发现确实是可以自适应!这基本就可以确认原因了,就是我们菜单收缩的时候,是有一定时间的,我们要等到菜单收缩完成之后再拿dom元素赋值给我们的svg宽高,经过测试我们把延迟写到300毫秒就可以了。 

最终结论就是:

如果是一般情况下,我们都不需要调用initWH方法,默认宽高也是100% * 100%,并且监听了window的resize方法,重置宽高。
特殊情况下,可以选择调用initWH方法重置宽高,但是一定是得等dom元素更新完成之后再去调用,要不然拿到的宽度也不是最终变化完的宽高,导致不能自适应,就像我这个例子,菜单展开收缩的时候,我们要延迟一会儿再去调用initWH就可以了

我这个例子最终的解决方案就是,监听菜单展开收缩的变化,当改变的时候延迟3秒调用initWH方法就可以了! 

<template>
  <div class="home">
    <div class="lt">
      <div class="branch"></div>
      <div class="branch"></div>
      <div class="branch"></div>
    </div>
    <div class="cen">
      <div class="cen-top">
        <dv-border-box-8 ref="borderBox"> </dv-border-box-8>
      </div>
      <div class="cen-bot"></div>
    </div>
    <div class="rt">
      <div class="branch"></div>
      <div class="branch"></div>
      <div class="branch"></div>
    </div>
  </div>
</template>
<script>
export default {
  computed: {
    isCollapse() {
      return this.$store.state.common.isCollapse;
    }
  },
  watch: {
    isCollapse() {
      setTimeout(() => {
        this.$refs.borderBox.initWH()
      }, 300)
    }
  }
}
</script>

最终效果图: 

;