【vue】a-tree中使用自定义指令监听DOM元素变化

【需求】

在antdesign中的a-tree组件时,为每个节点右侧添加了复选框以及多选操作,由于ant官方tree的逻辑并不支持项目的业务逻辑,因此手撸了这边的逻辑,过程中遇到了两个问题。如下图所示:

【vue】a-tree中使用自定义指令监听DOM元素变化_第1张图片

【解决办法】

问题1,为右侧复选框区域添加sticky布局即可,代码如下:

...
.check-box {
  position: sticky;
  background-color: #fafbfc;
  padding-right: 10px;
  margin-top: -24px;
  text-align: right;
}
.check-box-1 {
  width: 30px;
  left: 220px;
}
.check-box-2 {
  width: 50px;
  left: 204px;
}

问题2,涉及到动态变化,一开始准备通过变量统一改改变,但每个树的节点,位置状态都不同,无法进行统一设置,因此想到了自定义指令监听,代码如下:

    
        
      

v-titleBoxChange="titleBoxChange"为例,其他可以不用过多关注

包含三部分

1、DOM绑定,即 v-titleBoxChange="titleBoxChange"

2、注册指令

在directives中注册,directives和methods、mounted等同级。如下代码所示,bind中进行绑定,设置定时器,一旦有变化就通过binding.value({})回调函数进行更新。

3、函数中输出DOM变化

directives: {
    titleBoxChange: {
      bind(el, binding) {
        console.log(el, '绑定', binding)
        let titleBoxDomLength = 0
        function titleBoxDomLengthChange() {
          const titleBoxDom = el.getElementsByClassName('title-box')
          if (titleBoxDomLength != titleBoxDom?.length) {
            binding.value({
              titleBoxDomLength: titleBoxDom?.length ? titleBoxDom.length : 0, // 关键(这传入的是函数,所以执行此函数)
              titleBoxDom: titleBoxDom,
            })
          }
          titleBoxDomLength = titleBoxDom?.length ? titleBoxDom.length : 0
        }
        el.__vueSetInterval__ = setInterval(titleBoxDomLengthChange, 300)
      },
      unbind(el) {
        console.log(el, '解绑')
        clearInterval(el.__vueSetInterval__)
      },
    },
  },
methods: {
    titleBoxChange({ titleBoxDomLength, titleBoxDom }) {
      let maxWidth = 0
      // 获取最大宽度
      for (let i = 0; i < titleBoxDomLength; i++) {
        const spanDom = titleBoxDom[i].firstChild
        maxWidth =
          maxWidth > spanDom.offsetWidth ? maxWidth : spanDom.offsetWidth
      }
      maxWidth += 100
      // 更新宽度
      for (let i = 0; i < titleBoxDomLength; i++) {
        let moveLeft = 0
        let tempDom = titleBoxDom[i].parentNode.parentNode.parentNode.parentNode // 最近的url
        while (tempDom.tagName == 'UL') {
          moveLeft += parseFloat(
            window
              .getComputedStyle(tempDom, null)
              .getPropertyValue('padding-left')
          )
          tempDom = tempDom.parentNode.parentNode
        }
        titleBoxDom[i].setAttribute('style', `width:${maxWidth - moveLeft}px`)
      }

      this.setSelectDomWidth() // 设置选中状态
    },
}

你可能感兴趣的:(VUE,前端,vue.js,javascript,前端)