
image.png
功能需求:頁面左右布局,左邊初始定寬512px,右側(cè)寬度 flex:1,分割線中間有拖拽按鈕,拖拽時(shí) 左側(cè)的寬度最大寬度是現(xiàn)在寬度+現(xiàn)在寬的的50%。最小寬度是初始寬度的一半 。
解決思路:在mounted生命周期,監(jiān)聽分割線DOM的onmousedown事件,在拖拽過程中動(dòng)態(tài)計(jì)算,然后賦值改變左右DOM元素的寬度。
實(shí)現(xiàn)代碼:(class類里用的tailwindcss)
<!--template-->
<div class={['flex h-full']}>
<div class={[style.subject__left_container, 'relative']} ref='leftDom'>
左側(cè)內(nèi)容區(qū)
</div>
<div class='flex-1 flex h-full relative'>
{this.envHost && <iframe src={this.envHost} style='height:100%; width:100%'/>}
{!this.envHost && <Empty/>
</div>
</div>
<!--css-->
.subject__left_container {
width: 512px;
border-right: 1px solid #e8e8e8;
}
<!--js-->
// mounted生命周期
public mounted() {
this.leftDom = this.$refs.leftDom;
let moveDom = this.$refs.moveDom;
(moveDom as any).onmousedown = (e: any) => {
this.clientStartX = e.clientX;
e.preventDefault();
document.onmousemove = (e) => {
this.moveHandle(e.clientX, this.leftDom);
};
document.onmouseup = () => {
document.onmouseup = null;
document.onmousemove = null;
};
};
}
public moveHandle(nowClientX: number, letfDom: any) {
let computedX = nowClientX - this.clientStartX;
let leftBoxWidth = parseInt(letfDom.clientWidth);
let changeWidth = leftBoxWidth + computedX;
if (changeWidth < 256) {
changeWidth = 256;
}
if (changeWidth > 768) {
changeWidth = 768;
}
letfDom.style.width = changeWidth + 'px';
this.clientStartX = nowClientX;
}
??注意: 以上代碼對(duì)左右布局都是div的話 是ok的,但是當(dāng)我們右邊的布局里有iframe,單純這么寫,拖拽時(shí)鼠標(biāo)移入右側(cè)iframe區(qū)時(shí)會(huì)拖不動(dòng),或者無法根據(jù)鼠標(biāo)移動(dòng),快速響應(yīng),甚至在監(jiān)聽鼠標(biāo)的按下和松開事件上都有明顯的卡頓問題。
解決方法:在拖動(dòng)的時(shí)候,在iframe上方添加一個(gè)透明的遮罩層,然后在停止拖拽的時(shí)候讓其消失。
<!--template-->
<div class={['flex h-full']}>
<div class={[style.subject__left_container, 'relative']} ref='leftDom'>
左側(cè)內(nèi)容區(qū)
</div>
<div class='flex-1 flex h-full relative'>
<div class={style.iframe__div} ref='iframeDiv'/>
{this.envHost && <iframe src={this.envHost} style='height:100%; width:100%'/>}
{!this.envHost && <Empty/>
</div>
</div>
<!--css-->
.subject__left_container {
width: 512px;
border-right: 1px solid #e8e8e8;
}
.iframe__div {
width:100%;
height: 100%;
position: absolute;
z-index: 999;
filter: alpha(opacity=0);
opacity: 0;
background: transparent;
display: none;
}
<!--js-->
// mounted生命周期
public mounted() {
this.leftDom = this.$refs.leftDom;
let moveDom = this.$refs.moveDom;
var iframeDiv = this.$refs.iframeDiv;
(moveDom as any).onmousedown = (e: any) => {
this.clientStartX = e.clientX;
e.preventDefault();
if (iframeDiv) {
(iframeDiv as any).style.display = 'block';
}
document.onmousemove = (e) => {
this.moveHandle(e.clientX, this.leftDom);
};
document.onmouseup = () => {
if (iframeDiv) {
(iframeDiv as any).style.display = 'none';
}
document.onmouseup = null;
document.onmousemove = null;
};
};
}
public moveHandle(nowClientX: number, letfDom: any) {
let computedX = nowClientX - this.clientStartX;
let leftBoxWidth = parseInt(letfDom.clientWidth);
let changeWidth = leftBoxWidth + computedX;
if (changeWidth < 256) {
changeWidth = 256;
}
if (changeWidth > 768) {
changeWidth = 768;
}
letfDom.style.width = changeWidth + 'px';
this.clientStartX = nowClientX;
}