vue3 可拖動(dòng)的左右面板分割組件實(shí)現(xiàn)
最近在使用vue的時(shí)候,遇到一個(gè)需求,實(shí)現(xiàn)左右div可通過(guò)中間部分拖拽調(diào)整寬度,本文就整理一下,分享給大家,具體如下:
效果圖

分解組件
整體使用flex布局
左側(cè)面板
- 面板的具體內(nèi)容通過(guò)slot具名插槽傳入。
- title通過(guò)prop傳入
- 可拖動(dòng),為了保證內(nèi)容樣式不會(huì)被拖動(dòng)所破壞,對(duì)面板的寬度設(shè)定最大值/最小值
右側(cè)面板
- 右側(cè)面板寬度隨著左側(cè)面板的寬度變化而變化,此處需注意,內(nèi)容的寬度使用flex-auto自動(dòng)適應(yīng)。
- 需要做移動(dòng)端的自適應(yīng)。
- 自適應(yīng)使用tailwind的媒體查詢

入?yún)⒎纸?br />
props
- @param {Number} maxWidth 最大寬度
- @param {Number} minWidth 最小寬度
- @param {String} leftTitle 左標(biāo)題
- @param {String} rightTitle 右標(biāo)題?
- @param {Boolean} sotoreage 是否存儲(chǔ)與localstorege
slots
- left-content {Element} 左側(cè)內(nèi)容
- right-content {Element} 右側(cè)內(nèi)容
具體實(shí)現(xiàn)
如何拖動(dòng)呢?
在左側(cè)面板與右側(cè)面板之間添加一個(gè)隱藏的盒子,我將這個(gè)盒子隱藏在box-shadow之中。具體事件放在這個(gè)div中實(shí)現(xiàn)
<div id="line" class="w-2 cursor-move hidden md4:block"onMousedown={hnadleMouseDown}>
</div>
事件監(jiān)聽(tīng)
const hnadleMouseDown = (evt: MouseEvent) => {
/* 獲取起始點(diǎn)位,并存儲(chǔ) */
let { pageX, pageY } = evt;
basePosition.pageX = pageX;
basePosition.pageY = pageY;
/* 監(jiān)聽(tīng)鼠標(biāo)的移動(dòng)事件 */
document.addEventListener("mousemove", handleMouseMove);
document.addEventListener("mouseup", handleMouseUp);
};
const handleMouseMove = evt => {
/* 阻止瀏覽器默認(rèn)事件,防止觸發(fā)瀏覽器的手勢(shì)功能 */
evt.preventDefault();
/* 設(shè)置定時(shí)器,防止dom多次回流 */
clearTimeout(timer.value);
timer.value = setTimeout(() => {
let { pageX } = evt;
const baseDiv = document.querySelector(".right-border-shadow");
/* 處理寬度,是否處于最大值/最小值之間 */
let baseWidth: Number | undefined =
Number(baseDiv?.clientWidth) + (pageX - basePosition.pageX);
baseWidth =
baseWidth > Number(props?.maxWidth) ? props.maxWidth : baseWidth;
baseWidth =
Number(baseWidth) < Number(props?.minWidth)
? props.minWidth
: baseWidth;
baseDiv?.setAttribute("style", `width:${baseWidth}px`);
/* emit寬度改變的事件 */
ctx.emit("drugend");
/* 存儲(chǔ)到store */
setStore(baseWidth);
}, 50);
};
const handleMouseUp = evt => {
/* 結(jié)束拖動(dòng)之后,取消事件監(jiān)聽(tīng),并emit出最終寬度 */
const width = document.querySelector(".right-border-shadow")?.clientWidth;
document.removeEventListener("mousemove", handleMouseMove);
document.removeEventListener("mouseup", handleMouseUp);
ctx.emit("drugend", width);
};
寬度處理
style={`width:${
store.get("split-width")
? store.get("split-width")
: props.minWidth
? props.minWidth
: 384
}px`}
優(yōu)化
手動(dòng)改變?yōu)g覽器視窗寬度
nextTick(() => {
ctx.emit("load", ctx);
MutationObserver = window.MutationObserver;
if (MutationObserver) {
/* 監(jiān)聽(tīng)瀏覽器的窗口變化,在部分情況下需要這個(gè)api */
mo = new MutationObserver(function() {
const __wm = document.querySelector("#rezie-id");
// 只在__wm元素變動(dòng)才重新調(diào)用 __canvasWM
if (!__wm) {
// 避免一直觸發(fā)
mo.disconnect();
mo = null;
ctx.emit("resize");
}
});
mo.observe(document.querySelector("#rezie-id"), {
attributes: true,
subtree: true,
childList: true,
});
}
});
未生效,求指點(diǎn)
bug
父組件的onMounted鉤子中獲取子元素的slot元素節(jié)點(diǎn)報(bào)錯(cuò),為null。目前的解決辦法是在子組件的onMounted鉤子中拋出一個(gè)load事件,父組件使用onLoad去處理接下來(lái)的邏輯。
git地址
到此這篇關(guān)于vue3 可拖動(dòng)的左右面板分割組件實(shí)現(xiàn)的文章就介紹到這了,更多相關(guān)vue3 可拖動(dòng)左右分割面板內(nèi)容請(qǐng)搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
相關(guān)文章
詳解如何搭建mpvue框架搭配vant組件庫(kù)的小程序項(xiàng)目
這篇文章主要介紹了詳解如何搭建mpvue框架搭配vant組件庫(kù)的小程序項(xiàng)目,小編覺(jué)得挺不錯(cuò)的,現(xiàn)在分享給大家,也給大家做個(gè)參考。一起跟隨小編過(guò)來(lái)看看吧2019-05-05
vue如何實(shí)現(xiàn)路由跳轉(zhuǎn)到外部鏈接界面
這篇文章主要介紹了vue如何實(shí)現(xiàn)路由跳轉(zhuǎn)到外部鏈接界面,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。2022-10-10
vue實(shí)現(xiàn)監(jiān)聽(tīng)localstorage值變化
這篇文章主要介紹了vue實(shí)現(xiàn)監(jiān)聽(tīng)localstorage值變化,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。如有錯(cuò)誤或未考慮完全的地方,望不吝賜教2022-08-08
VUE3開(kāi)箱即用的音頻播放組件完整代碼(基于原生audio)
Vue3開(kāi)箱即用的框架有很多選擇,下面這篇文章主要介紹了VUE3開(kāi)箱即用的音頻播放組件(基于原生audio)的相關(guān)資料,文中通過(guò)代碼介紹的非常詳細(xì),需要的朋友可以參考下2024-09-09
vue實(shí)現(xiàn)點(diǎn)擊按鈕切換背景顏色的示例代碼
這篇文章主要介紹了用vue簡(jiǎn)單的實(shí)現(xiàn)點(diǎn)擊按鈕切換背景顏色,本文通過(guò)實(shí)例代碼給大家介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或工作具有一定的參考借鑒價(jià)值,需要的朋友可以參考下2020-06-06
Vue+axios 實(shí)現(xiàn)http攔截及路由攔截實(shí)例
這篇文章主要介紹了Vue+axios 實(shí)現(xiàn)http攔截及路由攔截 ,小編覺(jué)得挺不錯(cuò)的,現(xiàn)在分享給大家,也給大家做個(gè)參考。一起跟隨小編過(guò)來(lái)看看吧2017-04-04
關(guān)于VUE點(diǎn)擊父組件按鈕跳轉(zhuǎn)到子組件的問(wèn)題及解決方案
本文主要介紹了在Vue框架中,如何通過(guò)父組件的點(diǎn)擊事件打開(kāi)子組件中的彈窗并展示表格內(nèi)容,主要步驟包括在父組件中定義數(shù)據(jù)屬性,創(chuàng)建并定義子組件的彈窗和表格內(nèi)容,通過(guò)props屬性和自定義事件實(shí)現(xiàn)父子組件間的數(shù)據(jù)傳遞和方法調(diào)用2024-10-10
Vue.js實(shí)現(xiàn)一個(gè)SPA登錄頁(yè)面的過(guò)程【推薦】
本篇文章主要介紹了Vue.js寫(xiě)一個(gè)SPA登錄頁(yè)面過(guò)程的相關(guān)知識(shí),具有很好的參考價(jià)值。下面跟著小編一起來(lái)看下吧2017-04-04

