基于vue3的splitter组件

基于vue3的splitter组件

基于vue2版(https://blog.csdn.net/losedguest/article/details/106281367)
修改如下(SpliterVbox.vue)

<template>
  <div class="spliter-box" ref="spliterBox">
    <div class="spliter-left" ref="spliterLeft" :style="{ width: leftWidth + 'px' }"
      ><slot name="leftBox"></slot
    ></div>
    <div
      class="spliter-line"
      ref="spliterLine"
      :style="{ left: leftWidth + 'px' }"
      @mousedown.stop="ChangeLeftWith"
    >
      <i></i
      ><span
        class="ico spliter-ico-left"
        :class="{ 'spliter-ico-right': unexpand }"
        @click.stop="ToggleExpand"
      ></span
    ></div>
    <div
      class="spliter-right"
      ref="spliterRight"
      :style="{ left: leftWidth + 10 + 'px', width: 'calc(100% - ' + (leftWidth + 10) + 'px)' }"
      ><slot name="rightBox"></slot
    ></div>
  </div>
</template>
 
<script setup>
import { ref, onMounted } from 'vue';

let oldLeftWidth = 200,
  leftWidth = ref(200), // 左侧栏宽度
  unexpand = ref(false), // 左侧栏是否折叠
  MaxWidth = ref(0);

const spliterBox = ref(null);
const spliterLine = ref(null);
const spliterLeft = ref(null);
const spliterRight = ref(null);
onMounted(() => {
  MaxWidth.value = spliterBox.value.clientWidth - spliterLine.value.offsetWidth;
});

function ToggleExpand() {
  unexpand.value = !unexpand.value;
  if (!unexpand.value) {
    // 展开
    leftWidth.value = oldLeftWidth; // 还原原始宽度
  } else {
    // 收起来
    oldLeftWidth = leftWidth.value; // 记住原始的宽度
    leftWidth.value = 0;
  }
}
function ChangeLeftWith(e) {
  let disX = (e || event).clientX; //鼠標起始橫向距離
  let vleft = spliterLine.value.offsetLeft; //記錄起始的分割線的右邊距
  document.onmousemove = function (e) {
    let iT = vleft + ((e || event).clientX - disX); //分割線右邊距+移動距離
    spliterLine.value.style.margin = 0;
    iT < 0 && (iT = 0); //分割線超出左邊
    iT > MaxWidth && (iT = MaxWidth.value); //分割線超出右邊
    leftWidth.value = iT;
    return false;
  };
  document.onmouseup = function () {
    document.onmousemove = null;
    document.onmouseup = null;
    spliterLine.value.releaseCapture && spliterLine.value.releaseCapture();
  };
  spliterLine.value.setCapture && spliterLine.value.setCapture();
  return false;
}
</script>
 
<style>
.spliter-box {
  width: 100%;
  height: 100%;
  overflow: hidden;
}
.spliter-left {
  position: absolute;
  height: 100%;
  overflow: hidden;
}
.spliter-right {
  position: absolute;
  height: 100%;
  overflow: hidden;
}
.spliter-line {
  position: absolute;
  width: 6px;
  height: 100%;
  background-color: aliceblue;
  cursor: col-resize;
  border: 1px solid #00ffff;
  overflow: hidden;
  text-align: center;
  display: table-cell;
  vertical-align: middle;
}

.spliter-line i {
  display: inline-block;
  height: 100%;
  vertical-align: middle;
}
.spliter-line span {
  width: 6px;
  height: 10px;
  vertical-align: middle;
}
.spliter-ico-left {
  background-image: url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAYAAAAKCAYAAACXDi8zAAAAGXRFWHRTb2Z0d2FyZQBBZG9iZSBJbWFnZVJlYWR5ccllPAAAAyBpVFh0WE1MOmNvbS5hZG9iZS54bXAAAAAAADw/eHBhY2tldCBiZWdpbj0i77u/IiBpZD0iVzVNME1wQ2VoaUh6cmVTek5UY3prYzlkIj8+IDx4OnhtcG1ldGEgeG1sbnM6eD0iYWRvYmU6bnM6bWV0YS8iIHg6eG1wdGs9IkFkb2JlIFhNUCBDb3JlIDUuMC1jMDYwIDYxLjEzNDc3NywgMjAxMC8wMi8xMi0xNzozMjowMCAgICAgICAgIj4gPHJkZjpSREYgeG1sbnM6cmRmPSJodHRwOi8vd3d3LnczLm9yZy8xOTk5LzAyLzIyLXJkZi1zeW50YXgtbnMjIj4gPHJkZjpEZXNjcmlwdGlvbiByZGY6YWJvdXQ9IiIgeG1sbnM6eG1wPSJodHRwOi8vbnMuYWRvYmUuY29tL3hhcC8xLjAvIiB4bWxuczp4bXBNTT0iaHR0cDovL25zLmFkb2JlLmNvbS94YXAvMS4wL21tLyIgeG1sbnM6c3RSZWY9Imh0dHA6Ly9ucy5hZG9iZS5jb20veGFwLzEuMC9zVHlwZS9SZXNvdXJjZVJlZiMiIHhtcDpDcmVhdG9yVG9vbD0iQWRvYmUgUGhvdG9zaG9wIENTNSBXaW5kb3dzIiB4bXBNTTpJbnN0YW5jZUlEPSJ4bXAuaWlkOkE0QTk1QTVBRTYwMTExRTdBRjQxOERENjkwQUFCMDI0IiB4bXBNTTpEb2N1bWVudElEPSJ4bXAuZGlkOkE0QTk1QTVCRTYwMTExRTdBRjQxOERENjkwQUFCMDI0Ij4gPHhtcE1NOkRlcml2ZWRGcm9tIHN0UmVmOmluc3RhbmNlSUQ9InhtcC5paWQ6QTRBOTVBNThFNjAxMTFFN0FGNDE4REQ2OTBBQUIwMjQiIHN0UmVmOmRvY3VtZW50SUQ9InhtcC5kaWQ6QTRBOTVBNTlFNjAxMTFFN0FGNDE4REQ2OTBBQUIwMjQiLz4gPC9yZGY6RGVzY3JpcHRpb24+IDwvcmRmOlJERj4gPC94OnhtcG1ldGE+IDw/eHBhY2tldCBlbmQ9InIiPz79g2URAAAAbElEQVR42mL8//8/AzJgjJv638dAgYEBJAHDDLFT/jOsf/kfRDMhq2QIDIHrZIILuruhGMkEFtTXYWD4+pWB4c8fVB3YANP/RdmMDBevMDBwczMwsLCg6gBL7tyFqgPGAEuuX4PwDy4PAgQYADcaMJfVpu88AAAAAElFTkSuQmCC);
  background-repeat: no-repeat;
  background-position: center;
  background-size: contain;
  display: inline-block;
}
.spliter-ico-right {
  transform: rotate(180deg);
  -ms-transform: rotate(180deg); /* IE 9 */
  -webkit-transform: rotate(180deg); /* Safari and Chrome */
}
.spliter-line .ico {
  cursor: pointer;
}
</style>

使用方式不变

<template>
  <div id="app">   
    <div  style="width:400px;height:300px;margin-left:200px;border:1px solid;overflow:visible;position:relative;">
    <SpliterVbox>
      <template v-slot:leftBox>haha</template>
      <template v-slot:rightBox>hehe</template>
    </SpliterVbox>
    </div>
  </div>
</template>
 
<script>
import SpliterVbox from './components/SpliterVbox.vue'
 
</script>
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 2
    评论
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值