国外基于vue的分屏插件
Splitpanes:https://antoniandre.github.io/splitpanes/
自己手写一个简易版的分屏组件
为什么不用Splitpanes?在具体项目中,我发现Splitpanes存在bug,在使用Splitpanes时,如果里面的其中一个分屏出现iframe,则每次调整中间的分屏条都会很卡顿,貌似官方也没给具体的解决方案(查了很多种原因,试了很多种方解决都不行)。所以我这边又找网上资料,参照的写了个基于vue2版本的分屏组件。
具体实现
废话不多说,直接上代码
<template>
<div class="pane" :style="{ flexDirection: direction }" ref="pane">
<div class="left" :style="lengthType + paneLengthValue" v-show="leftVisable">
<slot name="left">
</slot>
</div>
<div
class="trigger"
:style="lengthType + triggerLengthValue"
@mousedown="handleMouseDown"
title="拖动调整"
></div>
<div class="iframeDiv" ref="iframeDiv" v-show="leftVisable && rightVisable"></div>
<div class="right" v-show="rightVisable">
<slot name="right">
</slot>
</div>
</div>
</template>
<script>
export default {
props: {
direction: {
//切屏方向
type: String,
default: "row",
},
paneLengthPercent: {
//左侧切屏宽度%
type: Number,
default: 50,
},
triggerLength: {
//滑块宽度px
type: Number,
default: 10,
},
leftVisable: {
type: Boolean,
default: ()=>true
},
rightVisable: {
type: Boolean,
default: ()=>true
},
triggerClick:{
}
},
components: {},
data() {
return {
triggerLeftOffset: 0, //鼠标距离滑轮左侧顶边距离
};
},
computed: {
lengthType() {
if (this.direction === "row") {
return "height:100%;width:";
} else {
return "width:100%;height:";
}
},
paneLengthValue() {
return `calc(${this.paneLengthPercent}% - ${
this.triggerLength / 2 + "px"
})`;
},
triggerLengthValue() {
return `${this.triggerLength + "px"}`;
},
pane() {
return this.$refs.pane;
},
iframeDiv() {
return this.$refs.iframeDiv;
},
},
watch:{
leftVisable(val){
console.log('leftVisable:',val)
if(val){
if(this.rightVisable){
this.paneLengthPercent = 50
this.triggerLength = 10
}else{
this.paneLengthPercent = 100
this.triggerLength = 0
}
}else{
this.paneLengthPercent = 0
this.triggerLength = 0
}
},
rightVisable(val){
console.log('rightVisable:',val)
if(val){
if(this.leftVisable){
this.paneLengthPercent = 50
this.triggerLength = 10
}else{
this.paneLengthPercent = 0
this.triggerLength = 0
}
}else{
if(this.leftVisable){
this.paneLengthPercent = 100
this.triggerLength = 0
}else{
this.paneLengthPercent = 0
this.triggerLength = 0
}
}
}
},
methods: {
// 按下滑动器后
handleMouseDown(e) {
console.log(e)
document.addEventListener("mousemove", this.handleMouseMove);
document.addEventListener("mouseup", this.handleMouseUp);
//计算滑轮宽度
if (this.direction === "row") {
this.triggerLeftOffset =
e.pageX - e.srcElement.getBoundingClientRect().left;
} else {
this.triggerLeftOffset =
e.pageY - e.srcElement.getBoundingClientRect().top;
}
this.changeIframeDivStyle("");
},
// 按下滑动器后移动
handleMouseMove(e) {
const clientRect = this.pane.getBoundingClientRect(); //容器dom
if (this.direction == "row") {
const offset =
e.pageX -
clientRect.left -
this.triggerLeftOffset +
this.triggerLength / 2;
this.paneLengthPercent = (offset / clientRect.width) * 100;
} else {
const offset =
e.pageY -
clientRect.height -
this.triggerLeftOffset +
this.triggerLength / 2;
this.paneLengthPercent = (offset / clientRect.height) * 100;
}
},
//鼠标松开
handleMouseUp() {
this.changeIframeDivStyle("none");
document.removeEventListener("mousemove", this.handleMouseMove);
},
changeIframeDivStyle(display) {
this.iframeDiv.style.display = display;
},
},
mounted() {
this.changeIframeDivStyle("none");
},
};
</script>
<style>
.pane {
display: flex;
height: 100vh;
position: relative;
}
.trigger {
background-color: rgb(166, 175, 184);
user-select: none;
}
.trigger:hover {
cursor: col-resize;
background-color: rgb(112, 126, 141);
}
.left {
position: relative;
}
.right {
flex: 1;
}
.iframeDiv {
width: 100%;
height: 100%;
position: absolute;
z-index: 9999;
filter: alpha(opacity=0);
opacity: 0;
background: transparent;
}
</style>
(注意:上面的iframeDiv遮罩层就可以解决卡顿问题)
具体使用
import SplitPane from '~/SplitPane'
<SplitPane :leftVisable="iframeCertShow" :rightVisable="iframeOriginShow">
<template v-slot:left>
<div >
<iframe
ref="cert"
:src="iframeSrcCert"
frameborder="0"
width="100%"
style="height: 98vh; overflow-x: auto"
/>
</div>
</template>
<template v-slot:right >
<div >
<iframe
ref="orgin"
:src="iframeSrcOrigin"
frameborder="0"
style="height: 98vh; overflow-x: auto"
width="100%"
/>
</div>
</template>
</SplitPane>