【sgSpliter】自定義組件:可調整寬度、高度、折疊的分割線

sgSpliter.vue?

<template><!-- 注意:父組件position必須是relative、absolute或fixed,不建議直接在綁定:data后面用"{屬性}",建議單獨在script中聲明data,避免拖拽過程重復調用 --><div :class="$options.name" :placement="placement" @mousedown="__addWindowEvents"><divv-if="showArrowBtn"class="arrow-btn"@click="clickArrowBtn"@mousedown.stop:styleType="arrowBtnStyleType":collapse="collapse"><!-- 箭頭在父組件的最左側 --><template v-if="placement === `left`"><i class="el-icon-arrow-left" v-if="collapse" /><i class="el-icon-arrow-right" v-else /></template><!-- 箭頭在父組件的最右側 --><template v-if="placement === `right`"><i class="el-icon-arrow-right" v-if="collapse" /><i class="el-icon-arrow-left" v-else /></template><!-- 箭頭在父組件的最上側 --><template v-if="placement === `top`"><i class="el-icon-arrow-up" v-if="collapse" /><i class="el-icon-arrow-down" v-else /></template><!-- 箭頭在父組件的最下側 --><template v-if="placement === `bottom`"><i class="el-icon-arrow-down" v-if="collapse" /><i class="el-icon-arrow-up" v-else /></template></div></div>
</template>
<script>
export default {name: "sgSpliter",components: {},data() {return {form: {},collapse: false,showArrowBtn: true,placement: `right`,parent: null,defaultSize: 200, //當拖拽區域到0,再點擊箭頭展開的默認寬度nearEdgeSize: 5, //當拖拽寬度小于此寬度,自動折疊到0minSize: null, //可選,指定 最小寬度maxSize: null, //可選,指定 最大寬度size: null,size_bk: null,arrowBtnStyleType: `default`, //按鈕風格:白色背景default、藍色背景bluesplitBarSize: 1, //可選,分隔條大小,默認 2pxresizable: true, //可選,指定 是否可調整大小,會影響相鄰};},props: ["data"],computed: {},watch: {data: {handler(newValue, oldValue) {// console.log(`深度監聽${this.$options.name}:`, newValue, oldValue);if (Object.keys(newValue || {}).length) {this.form = JSON.parse(JSON.stringify(newValue));this.$g.convertForm2ComponentParam(`showArrowBtn`, this);this.$g.convertForm2ComponentParam(`defaultSize`, this);this.$g.convertForm2ComponentParam(`nearEdgeSize`, this);this.$g.convertForm2ComponentParam(`minSize`, this);this.$g.convertForm2ComponentParam(`maxSize`, this);this.$g.convertForm2ComponentParam(`placement`, this);this.$g.convertForm2ComponentParam(`parent`, this);this.$g.convertForm2ComponentParam(`arrowBtnStyleType`, this);this.$g.convertForm2ComponentParam(`splitBarSize`, this);this.$g.convertForm2ComponentParam(`resizable`, this);this.form.hasOwnProperty("collapse") &&this.collapseSpliter({ collapse: this.form.collapse }); //允許外部控制默認折疊或展開this.$nextTick(() => {this.$el.style.setProperty(`--splitBarSize`, `${this.splitBarSize}px`); //js往css傳遞局部參數});// 不要在這里初始化size_bk,由于拖拽過程會重復觸發這里的代碼執行}},deep: true, //深度監聽immediate: true, //立即執行},size(size) {size <= this.nearEdgeSize && (size = 0);this.collapse = size === 0;this.$emit(`change`, { size });},},mounted() {this.$nextTick(() => {this.parent || (this.parent = this.$el.parentNode);if (this.parent) {let rect = this.parent.getBoundingClientRect();switch (this.placement) {case `left`: // 豎線在父組件的最左側case `right`: // 豎線在父組件的最右側this.size_bk = rect.width;break;case `top`: // 豎線在父組件的最上側case `bottom`: // 豎線在父組件的最下側this.size_bk = rect.height;break;default:}}});},beforeDestroy() {this.__removeWindowEvents();},methods: {//size發生變化的時候就做緩動效果changeTransitionSize() {let parent = this.parent;if (parent) {let attr = `${this.$options.name}-transitionSize`;parent.setAttribute(attr, true);setTimeout(() => parent.removeAttribute(attr), 200);}},clickArrowBtn($event) {this.collapseSpliter();this.$emit(`clickArrowBtn`, { $event, collapse: this.collapse });},collapseSpliter({ collapse } = {}) {this.collapse = collapse === undefined ? !this.collapse : collapse;let expandSize = this.size_bk > this.nearEdgeSize ? this.size_bk : this.defaultSize;this.changeTransitionSize();this.size = this.collapse ? 0 : expandSize;this.$emit(`change`, { size: this.size });this.$emit(`collapseSpliter`, { collapse });},bkSize(d) {this.size_bk = this.size;},__addWindowEvents() {this.__removeWindowEvents();addEventListener("mousemove", this.mousemove_window);addEventListener("mouseup", this.mouseup_window);},__removeWindowEvents() {removeEventListener("mousemove", this.mousemove_window);removeEventListener("mouseup", this.mouseup_window);},mousemove_window($event) {if (!this.resizable) return;this.parent || (this.parent = this.$el.parentNode);if (this.parent) {let { x, y } = $event,rect = this.parent.getBoundingClientRect(),size;switch (this.placement) {case `left`: // 豎線在父組件的最左側size = rect.x + rect.width - x;break;case `right`: // 豎線在父組件的最右側size = x - rect.x;break;case `top`: // 豎線在父組件的最上側size = rect.y + rect.height - y;break;case `bottom`: // 豎線在父組件的最下側size = y - rect.y;break;default:}this.minSize && size < this.minSize && (size = this.minSize);this.maxSize && size > this.maxSize && (size = this.maxSize);this.size = size;this.bkSize();} else {this.$message.error(`沒有獲取到父組件parent!`);}},mouseup_window($event) {this.__removeWindowEvents();this.$emit(`dragEnd`, { $event });},},
};
</script>
<style lang="scss" scoped>
$splitBarSize: var(--splitBarSize); //css獲取js傳遞的參數
.sgSpliter {z-index: 1;background-color: #efefef;position: absolute;left: 0;top: 0;right: 0;bottom: 0;position: absolute;.arrow-btn {transition: 0.382s;opacity: 0;pointer-events: none;// transform: translateY(50%); //防止托盤最小高度的時候還冒出一小截width: 20px;right: -20px;height: 20px;display: flex;justify-content: center;align-items: center;color: #409eff;background-color: white;font-size: 12px;position: absolute;margin: auto;box-sizing: border-box;cursor: pointer;&:hover {filter: brightness(1.1);}&[styleType="blue"] {color: white;background-color: #4f6bdf;}&[collapse] {opacity: 1;pointer-events: auto;}}// 位置----------------------------------------&[placement="left"],&[placement="right"] {cursor: col-resize;width: $splitBarSize;height: 100%;}&[placement="top"],&[placement="bottom"] {cursor: row-resize;width: 100%;height: $splitBarSize;}&[placement="left"] {left: 0;right: revert;.arrow-btn {left: revert;right: $splitBarSize;top: 0;bottom: 0;border-radius: 8px 0 0 8px;padding: 20px 0;box-shadow: -5px 0px 10px 0 rgba(0, 0, 0, 0.1);}}&[placement="right"] {left: revert;right: 0;.arrow-btn {left: $splitBarSize;right: revert;top: 0;bottom: 0;border-radius: 0 8px 8px 0;padding: 20px 0;box-shadow: 5px 0px 10px 0 rgba(0, 0, 0, 0.1);}}&[placement="top"] {top: 0;bottom: revert;.arrow-btn {left: 0;right: 0;top: revert;bottom: $splitBarSize;border-radius: 8px 8px 0 0;padding: 0 20px;box-shadow: 0px -5px 10px 0 rgba(0, 0, 0, 0.1);}}&[placement="bottom"] {top: revert;bottom: 0;.arrow-btn {left: 0;right: 0;top: $splitBarSize;bottom: revert;border-radius: 0 0 8px 8px;padding: 0 20px;box-shadow: 0px 5px 10px 0 rgba(0, 0, 0, 0.1);}}// ----------------------------------------&:hover {background-color: #b3d8ff;.arrow-btn {opacity: 1;pointer-events: auto;}}// 按下拖拽線條后出現的半透明區域&::after {content: "";transition: 0.382s;position: absolute;background-color: #409eff22;opacity: 0;}$splitOpacityBgExpandSize: 5px; //半透明延伸寬度$splitOpacityBgSize: calc(#{$splitOpacityBgExpandSize} * 2 + #{$splitBarSize});&[placement="left"],&[placement="right"] {&::after {width: $splitOpacityBgSize;height: 100%;left: -#{$splitOpacityBgExpandSize};top: 0;}}&[placement="top"],&[placement="bottom"] {&::after {width: 100%;height: $splitOpacityBgSize;left: 0;top: -#{$splitOpacityBgExpandSize};}}&:active {opacity: 1;background-color: #409eff;&::after {opacity: 1;}}
}
</style><style lang="scss">
[sgSpliter-transitionSize] {transition: 0.2s;
}
</style>

demo

<template><div :class="$options.name"><div class="left" :style="{ width: `${leftWidth}px` }"><sgSpliter :data="{ placement: `right` }" @change="leftWidth = $event.size" /></div><div class="right"><div class="top" :style="{ height: `${topHeight}px` }"><sgSpliter :data="{ placement: `bottom` }" @change="topHeight = $event.size" /></div><div class="bottom"><div class="left"><div class="top"></div><div class="bottom" :style="{ height: `${bottomHeight}px` }"><sgSpliter:data="{ placement: `top` }"@change="bottomHeight = $event.size"/></div></div><div class="right" :style="{ width: `${bottomWidth}px` }"><sgSpliter :data="{ placement: `left` }" @change="bottomWidth = $event.size" /></div></div></div></div>
</template>
<script>
import sgSpliter from "@/vue/components/admin/sgSpliter";
export default {name: `demoSpliter`,components: { sgSpliter },data() {return {leftWidth: 200,topHeight: 200,bottomHeight: 200,bottomWidth: 200,};},
};
</script>
<style lang="scss" scoped>
.demoSpliter {display: flex;& > .left {height: 100%;flex-shrink: 0;position: relative;box-sizing: border-box;border-right: 1px solid #eee;}& > .right {flex-grow: 1;display: flex;flex-direction: column;& > .top {flex-shrink: 0;width: 100%;position: relative;box-sizing: border-box;border-bottom: 1px solid #eee;}& > .bottom {flex-grow: 1;width: 100%;display: flex;& > .left {flex-grow: 1;height: 100%;display: flex;flex-direction: column;& > .top {flex-grow: 1;width: 100%;}& > .bottom {flex-shrink: 0;width: 100%;position: relative;box-sizing: border-box;border-top: 1px solid #eee;}}& > .right {flex-shrink: 0;height: 100%;position: relative;box-sizing: border-box;border-left: 1px solid #eee;}}}
}
</style>

本文來自互聯網用戶投稿,該文觀點僅代表作者本人,不代表本站立場。本站僅提供信息存儲空間服務,不擁有所有權,不承擔相關法律責任。
如若轉載,請注明出處:http://www.pswp.cn/news/901096.shtml
繁體地址,請注明出處:http://hk.pswp.cn/news/901096.shtml
英文地址,請注明出處:http://en.pswp.cn/news/901096.shtml

如若內容造成侵權/違法違規/事實不符,請聯系多彩編程網進行投訴反饋email:809451989@qq.com,一經查實,立即刪除!

相關文章

Ningx負載均衡

Ningx負載均衡 upstream(上游)配置負載均衡1、weight&#xff08;加權輪詢&#xff09;2、ip_hash&#xff08;負載均衡&#xff09;3、url hash負載均衡4、least_conn&#xff08;最小連接負載均衡&#xff09; upstream(上游)配置負載均衡 Nginx負載均衡 參考: nginx從安裝…

一個插件,免費使用所有頂級大模型(Deepseek,Gpt,Grok,Gemini)

DeepSider是一款集成于瀏覽器側邊欄的AI對話工具&#xff0c;可免費使用所有頂級大模型 包括GPT-4o&#xff0c;Grok3,Claude 3.5 Sonnet,Claude 3.7,Gemini 2.0&#xff0c;Deepseek R1滿血版等 以極簡交互與超快的響應速度&#xff0c;完成AI搜索、實時問答、內容創作、翻譯、…

眾趣科技丨數字孿生技術,賦能交通公共設施管理數字化升級

春節假期期間&#xff08;1 月 21 日至 2 月 4 日&#xff09;&#xff0c;作為中國春節申遺成功后的首個春運&#xff0c;交通出行格外火熱&#xff0c;全社會跨區域流動量超 23 億人次&#xff0c;這一數據創下了歷史新高。 面對如此龐大的客流量&#xff0c;傳統的交通管理方…

Linux 入門五:Makefile—— 從手動編譯到工程自動化的蛻變

一、概述&#xff1a;Makefile—— 工程編譯的 “智能指揮官” 1. 為什么需要 Makefile&#xff1f; 手動編譯的痛點&#xff1a;當工程包含數十個源文件時&#xff0c;每次修改都需重復輸入冗長的編譯命令&#xff08;如gcc file1.c file2.c -o app&#xff09;&#xff0c;…

Python-Django+vue二手電子設備交易平臺功能說明

?(^_-) 上千個精美定制模板,各類成品Java、Python、PHP、Android畢設項目,歡迎咨詢。 ?(^_-) 程序開發、技術解答、代碼講解、文檔,??文末獲取源碼+數據庫+文檔?? ??軟件下載 | 實戰案例 ??文章底部二維碼,可以聯系獲取軟件下載鏈接,及項目演示視頻。 本項目…

數據庫管理工具實戰:IDEA 與 DBeaver 連接 TDengine(二)

五、DBeaver 連接 TDengine 實戰 5.1 安裝 DBeaver 下載安裝包&#xff1a;訪問 DBeaver 官方網站&#xff08;https://dbeaver.io/download/ &#xff09;&#xff0c;根據你的操作系統選擇合適的安裝包。如果是 Windows 系統&#xff0c;下載.exe 格式的安裝文件&#xff1…

Spring Boot接口返回Long類型的數據時丟失精度的全局處理

1、問題 當實體類中的字段為Long類型時&#xff0c;通過Ajax請求返回給前段&#xff0c;在js中數據會丟失精度 直接通過postman請求或通過瀏覽器請求&#xff0c;看下響應則不會丟失精度 2、處理方式 1、使用JsonSerialize注解 JsonSerialize(using ToStringSerializer.…

英偉達Llama-3.1-Nemotron-Ultra-253B-v1語言模型論文快讀:FFN Fusion

FFN Fusion: Rethinking Sequential Computation in Large Language Models 代表模型&#xff1a;Llama-3.1-Nemotron-Ultra-253B-v1 1. 摘要 本文介紹了一種名為 FFN Fusion 的架構優化技術&#xff0c;旨在通過識別和利用自然并行化機會來減少大型語言模型&#xff08;LLM…

Django學習記錄-1

Django學習記錄-1 雖然網上教程都很多&#xff0c;但是感覺自己記錄一下才屬于自己&#xff0c;之后想找也方面一點&#xff0c;文采不佳看的不爽可繞道。 參考貼 從零開始的Django框架入門到實戰教程(內含實戰實例) - 01 創建項目與app、加入靜態文件、模板語法介紹&#xff…

Python爬蟲第7節-requests庫的高級用法

目錄 前言 一、文件上傳 二、Cookies 三、會話維持 四、SSL證書驗證 五、代理設置 六、超時設置 七、身份認證 八、Prepared Request 前言 上一節&#xff0c;我們認識了requests庫的基本用法&#xff0c;像發起GET、POST請求&#xff0c;以及了解Response對象是什么。…

Python 要致富先修路

今天準備在原有基礎上重新深入學習并記錄python學習進程。 # 整體思路 不廢話&#xff1a; 階段1&#xff1a;精選入門電子教程堅持學習&#xff1b; 階段2&#xff1a;跟著教程學習代碼思維&#xff0c;做好學習筆記并構建知識庫方便以后速查&#xff1b; 階段3&#xff…

微服務無感發布實踐:基于Nacos的客戶端緩存與故障轉移機制

微服務無感發布實踐&#xff1a;基于Nacos的客戶端緩存與故障轉移機制 背景與問題場景 在微服務架構中&#xff0c;服務的動態擴縮容、滾動升級是常態&#xff0c;而服務實例的上下線需通過注冊中心&#xff08;如Nacos&#xff09;實現服務發現的實時同步。但在實際生產環境…

2025年的Android NDK 快速開發入門

十年前寫過一篇介紹NDK開發的文章《Android實戰技巧之二十三&#xff1a;Android Studio的NDK開發》&#xff0c;今天看來已經發生了很多變化&#xff0c;NDK開發變得更加容易了。下面就寫一篇當下NDK開發快速入門。 **原生開發套件 (NDK) **是一套工具&#xff0c;使開發者能…

Shell 編程之條件語句

目錄 條件測試操作 文件測試 整數值比較 字符串比較 邏輯測試 if 條件語句 if語句的結構 1、單分支 if 語句 2、雙分支 if 語句 3、多分支 if 語句 if語句應用實例 1、單分支 if 語句應用 2、雙分支 if 語句應用 3、多分支 if 語句應用 case 分支語句 case語句的結構 case語…

【模板】縮點

洛谷p3387 思路: 算法:tarjan算法 根據題意,我們只要找到一個路徑,使得最終權重最大即可,首先,根據題目可知,如果一個點在一個環上,那么我們就將這整個環都選上,題目上允許我們能夠重復走,因此,我們可以將環縮成點,將環所稱點后,就可以轉換成樹,從沒有父節點的結點開始,我們向…

js觸發隱式類型轉換的場景

JavaScript 的隱式類型轉換&#xff08;Implicit Type Coercion&#xff09;會在某些操作或上下文中自動觸發&#xff0c;將值從一種類型轉換為另一種類型。以下是常見的觸發場景&#xff1a; 1. 使用 &#xff08;寬松相等&#xff09;比較時 會嘗試將兩邊的值轉換為相同類型后…

c++將jpg轉換為灰度圖

c將jpg轉換為灰度圖 step1:添加依賴 下載這兩個文件&#xff0c;放在cpp同一目錄下&#xff0c;編譯生成 https://github.com/nothings/stb/blob/master/stb_image_write.h https://github.com/nothings/stb/blob/master/stb_image.hstep2:C:\Users\wangrusheng\source\repos…

python——正則表達式

一、簡介 在 Python 中&#xff0c;正則表達式主要通過 re 模塊實現&#xff0c;用于字符串的匹配、查找、替換等操作。 二、Python的re模塊 使用前需要導入&#xff1a; import re 三、常用方法 方法描述re.match(pattern, string)從字符串開頭匹配&#xff0c;返回第一個匹…

Soybean Admin 配置vite兼容低版本瀏覽器、安卓電視瀏覽器(飛視瀏覽器)

環境 window10 pnpm 8.15.4 node 8.15.4 vite 5.1.4 soybean admin: 1.0.0 native-ui: 2.38.0 小米電視 MIUI TV版本&#xff1a;MiTV OS 2.7.1886(穩定版) 飛視瀏覽器&#xff1a;https://www.fenxm.com/1220.html在小米電視安裝飛視瀏覽器可以去小紅書查安裝教程&#xff1a…

系統與網絡安全------網絡通信原理(1)

資料整理于網絡資料、書本資料、AI&#xff0c;僅供個人學習參考。 文章目錄 網絡通信模型協議分層計算機網絡發展計算機網絡功能什么是協議為什么分層郵局實例 OSI模型OSI協議模型OSI七層模型OSI七層的功能簡介 TCP/IP模型OSI模型與TCP/IP模型TCP/IP協議族的組成各層PDU設備與…