Vue自定义组件——隐藏的中心线,拖动改变左右元素宽度

22 篇文章 1 订阅
19 篇文章 1 订阅

所需传参如下:

传入中心线左侧元素、右侧元素和外侧元素的className,实现拖拽改变左右元素的宽度

* @Props: 
    classNames:{
      box      String     外侧容器className
      left     String     左侧容器className
      @right   String     右侧容器className
    }
 -->

 这里要确保左右和外侧的元素className唯一,也可以自己改成查找id的。

<template>
  <div class="centerLine"></div>
</template>
<script>
import * as ApiCom from '@/api/common'
export default {
  name: 'centerLine',
  props: {
    //传入的左中右三个className
    classNames: {
      type: Object,
      default: () => {
        return {}
      },
    },
  },
  data() {
    return {
      screenWidth: document.body.clientWidth,
      leftMinWidth: 500, //左侧最小宽度
      rightMinWidth: 500, //右侧最小宽度
    }
  },
  mounted() {
    this.setEvent()
    window.addEventListener('centerLine', this.setWidth())
  },
  watch: {
    screenWidth(newVal, oldVal) {
      const centerLine = document.getElementsByClassName('centerLine')?.[0]
      let right = document.getElementsByClassName(this.classNames.right)?.[0]
      right.style.width = `${newVal - centerLine.offsetLeft}px`
    },
  },
  methods: {
    setWidth() {
      this.screenWidth = document.body.clientWidth
    },
    /**
    * @description: 设置鼠标事件
    * @return Boolean
    */
    setEvent() {
      const { classNames, leftMinWidth, rightMinWidth } = this
      let centerLine = document.getElementsByClassName('centerLine')?.[0]
      let left = document.getElementsByClassName(classNames.left)?.[0]
      let right = document.getElementsByClassName(classNames.right)?.[0]
      let box = document.getElementsByClassName(classNames.box)?.[0]
      let leftWidth
      // 鼠标按下事件
      centerLine.onmousedown = (e) => {
        const startX = e.clientX
        centerLine.left = centerLine.offsetLeft
        // 鼠标拖动事件
        document.onmousemove = (e) => {
          const endX = e.clientX
          leftWidth = centerLine.left + (endX - startX) // endx-startx移动的距离。centerLine.left+移动的距离 = 左边区域最后的宽度
          const rightWidth = box.clientWidth - centerLine.offsetWidth //右边区域的宽度 = 容器宽度 - 左边区域的宽度
          leftWidth < leftMinWidth && (leftWidth = leftMinWidth) // 左边区域的最小宽度
          leftWidth > rightWidth - rightMinWidth &&
            (leftWidth = rightWidth - rightMinWidth) //右边区域最小宽度
          centerLine.style.left = leftWidth // 设置左侧区域的宽度
          left.style.width = `${leftWidth}px`
          right.style.width = `${box.clientWidth - leftWidth - 12}px` //12是中心线的总宽度
        }
        // 鼠标松开事件
        document.onmouseup = (e) => {
          document.onmousemove = null
          document.onmouseup = null
          centerLine.releaseCapture?.() //不需要继续获得鼠标消息要调用ReleaseCapture()释放
          this.setDetailsWidth(leftWidth) //保存修改后的宽度
        }
        centerLine.setCapture?.() //指定窗口里设置鼠标捕获
        return false
      }
    },
  },
  beforeDestroy() {
    window.onresize = null
    window.removeEventListener('centerLine', this.setWidth()) //移除监听
  },
}
</script>
<style lang="stylus" scoped >
.centerLine {
  height: 200px;
  display: flex;
  align-items: center;
  cursor: col-resize;
  margin: auto 5px;
  border-left: 2px solid #b4b9c1;

  &:hover {
    height: calc(100% + 10px); // 超出左右一点点
    border-left: 2px dashed #409eff;
    margin: -5px 5px 0 5px;
  }
}
</style>
  • 3
    点赞
  • 6
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值