vue3 可拖動的左右面板分割組件實現(xiàn)
最近在使用vue的時候,遇到一個需求,實現(xiàn)左右div可通過中間部分拖拽調(diào)整寬度,本文就整理一下,分享給大家,具體如下:
效果圖
分解組件
整體使用flex布局
左側(cè)面板
- 面板的具體內(nèi)容通過slot具名插槽傳入。
- title通過prop傳入
- 可拖動,為了保證內(nèi)容樣式不會被拖動所破壞,對面板的寬度設(shè)定最大值/最小值
右側(cè)面板
- 右側(cè)面板寬度隨著左側(cè)面板的寬度變化而變化,此處需注意,內(nèi)容的寬度使用flex-auto自動適應(yī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 是否存儲與localstorege
slots
- left-content {Element} 左側(cè)內(nèi)容
- right-content {Element} 右側(cè)內(nèi)容
具體實現(xiàn)
如何拖動呢?
在左側(cè)面板與右側(cè)面板之間添加一個隱藏的盒子,我將這個盒子隱藏在box-shadow之中。具體事件放在這個div中實現(xiàn)
<div id="line" class="w-2 cursor-move hidden md4:block"onMousedown={hnadleMouseDown}> </div>
事件監(jiān)聽
const hnadleMouseDown = (evt: MouseEvent) => { /* 獲取起始點位,并存儲 */ let { pageX, pageY } = evt; basePosition.pageX = pageX; basePosition.pageY = pageY; /* 監(jiān)聽鼠標(biāo)的移動事件 */ document.addEventListener("mousemove", handleMouseMove); document.addEventListener("mouseup", handleMouseUp); }; const handleMouseMove = evt => { /* 阻止瀏覽器默認事件,防止觸發(fā)瀏覽器的手勢功能 */ evt.preventDefault(); /* 設(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"); /* 存儲到store */ setStore(baseWidth); }, 50); }; const handleMouseUp = evt => { /* 結(jié)束拖動之后,取消事件監(jiān)聽,并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)化
手動改變?yōu)g覽器視窗寬度
nextTick(() => { ctx.emit("load", ctx); MutationObserver = window.MutationObserver; if (MutationObserver) { /* 監(jiān)聽瀏覽器的窗口變化,在部分情況下需要這個api */ mo = new MutationObserver(function() { const __wm = document.querySelector("#rezie-id"); // 只在__wm元素變動才重新調(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, }); } });
未生效,求指點
bug
父組件的onMounted鉤子中獲取子元素的slot元素節(jié)點報錯,為null。目前的解決辦法是在子組件的onMounted鉤子中拋出一個load事件,父組件使用onLoad去處理接下來的邏輯。
git地址
到此這篇關(guān)于vue3 可拖動的左右面板分割組件實現(xiàn)的文章就介紹到這了,更多相關(guān)vue3 可拖動左右分割面板內(nèi)容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
相關(guān)文章
使用vue.js在頁面內(nèi)組件監(jiān)聽scroll事件的方法
今天小編就為大家分享一篇使用vue.js在頁面內(nèi)組件監(jiān)聽scroll事件的方法,具有很好的參考價值,希望對大家有所幫助。一起跟隨小編過來看看吧2018-09-09Vue動態(tài)獲取數(shù)據(jù)后控件不可編輯問題
這篇文章主要介紹了Vue動態(tài)獲取數(shù)據(jù)后控件不可編輯問題,具有很好的參考價值,希望對大家有所幫助。如有錯誤或未考慮完全的地方,望不吝賜教2022-04-04