## 如下圖面板左右分割實現效果


### 公共HTML代碼
``` html
? <div
? ? ref="splitPane"
? ? class="split-pane"
? ? :class="direction"
? ? :style="{ flexDirection: direction }"
? ? @mouseleave="handleMouseleaveParent"
? >
? ? <div
? ? ? v-if="$slots.left"
? ? ? class="pane pane-one"
? ? ? :style="directionStyle + ':' + triggerDistance"
? ? >
? ? ? <slot name="left" />
? ? </div>
? ? <div
? ? ? v-if="$slots.left && $slots.right"
? ? ? class="pane-trigger"
? ? ? :style="directionStyle + ':' + barWidthPX"
? ? ? @mousedown="handleMouseDown"
? ? />
? ? <div v-if="$slots.right" class="pane pane-right">
? ? ? <slot name="right" />
? ? </div>
? </div>
```
### 完整的邏輯代碼
感興趣的可以去查詢一下[`getBoundingClientRect`](https://developer.mozilla.org/zh-CN/docs/Web/API/Element/getBoundingClientRect)方法。
``` js
export default {
name: 'SplitPane',
props: {
direction: {
type: String,
default: 'row' // column
},
min: {
type: Number,
default: 10
},
max: {
type: Number,
default: 60
},
defaultPercent: {
// 區域1寬度 (%)
type: Number,
default: 15
},
triggerWidthBar: {
// 滑動器寬度 (px)
type: Number,
default: 10
}
},
data() {
return {
paneMovePercent: 50, // 區域1寬度 (%)
triggerLeftOffset: 0 // 鼠標距滑動器左(頂)側偏移量
}
},
computed: {
directionStyle() {
return this.direction === 'row' ? 'width' : 'height'
},
triggerDistance() {
return `calc(${this.paneMovePercent}% - ${this.triggerWidthBar / 2 +
'px'})`
},
barWidthPX() {
return this.triggerWidthBar + 'px'
}
},
mounted() {
this.paneMovePercent = this.defaultPercent
},
methods: {
// 按下滑動器
handleMouseDown(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
}
},
// 按下滑動器后移動鼠標
handleMouseMove(e) {
const clientRect = this.$refs.splitPane.getBoundingClientRect()
let paneMovePercent = 0
if (this.direction === 'row') {
const offset =
e.pageX -
clientRect.left -
this.triggerLeftOffset +
this.triggerWidthBar / 2
paneMovePercent = (offset / clientRect.width) * 100
} else {
const offset =
e.pageY -
clientRect.top -
this.triggerLeftOffset +
this.triggerWidthBar / 2
paneMovePercent = (offset / clientRect.height) * 100
}
if (paneMovePercent < this.min) {
paneMovePercent = this.min
}
if (paneMovePercent > this.max) {
paneMovePercent = this.max
}
this.paneMovePercent = paneMovePercent
// this.$emit('update:paneMovePercent', paneMovePercent)
},
handleMouseleaveParent() {
this.handleMouseUp()
},
// 松開滑動器
handleMouseUp() {
document.removeEventListener('mousemove', this.handleMouseMove)
}
}
}
```
### 樣式代碼
``` scss
.split-pane {
height: 100%;
width: 100%;
display: flex;
&.row {
.pane {
height: 100%;
}
.pane-trigger {
height: 100%;
cursor: col-resize;
}
}
&.column {
.pane {
width: 100%;
}
.pane-trigger {
width: 100%;
cursor: row-resize;
}
}
.pane-trigger {
background: #fff;
border-right: 1px solid $comBorder;
&:hover {
background: $comBorder;
}
}
.pane-right {
flex: 1;
}
}
```
- 首頁
- 2021年
- 基礎知識
- 同源策略
- 跨域
- css
- less
- scss
- reset
- 超出文本顯示省略號
- 默認滾動條
- 清除浮動
- line-height與vertical-align
- box-sizing
- 動畫
- 布局
- JavaScript
- 設計模式
- 深淺拷貝
- 排序
- canvas
- 防抖節流
- 獲取屏幕/可視區域寬高
- 正則
- 重繪重排
- rem換算
- 手寫算法
- apply、call和bind原理與實現
- this的理解-普通函數、箭頭函數
- node
- nodejs
- express
- koa
- egg
- 基于nodeJS的全棧項目
- 小程序
- 常見問題
- ec-canvas之橫豎屏切換重繪
- 公眾號后臺基本配置
- 小程序發布協議更新
- 小程序引入iconfont字體
- Uni-app
- 環境搭建
- 項目搭建
- 數據庫
- MySQL數據庫安裝
- 數據庫圖形化界面常用命令行
- cmd命令行操作數據庫
- Redis安裝
- APP
- 控制縮放meta
- GIT
- 常用命令
- vsCode
- 常用插件
- Ajax
- axios-services
- 文章
- 如何讓代碼更加優雅
- 虛擬滾動
- 網站收藏
- 防抖節流之定時器清除問題
- 號稱破解全網會員的腳本
- 資料筆記
- 資料筆記2
- 公司面試題
- 服務器相關
- 前端自動化部署-jenkins
- nginx.conf配置
- https添加證書
- shell基本命令
- 微型ssh-deploy前端部署插件
- webpack
- 深入理解loader
- 深入理解plugin
- webpack注意事項
- vite和webpack區別
- React
- react+antd搭建
- Vue
- vue-cli
- vue.config.js
- 面板分割左右拖動
- vvmily-admin-template
- v-if與v-for那個優先級高?
- 下載excel
- 導入excel
- Echart-China-Map
- vue-xlsx(解析excel)
- 給elementUI的el-table添加骨架
- cdn引入配置
- Vue2.x之defineProperty應用
- 徹底弄懂diff算法的key作用
- 復制模板內容
- 表格操作按鈕太多
- element常用組件二次封裝
- Vue3.x
- Vue3快速上手(第一天)
- Vue3.x快速上手(第二天)
- Vue3.x快速上手(第三天)
- vue3+element-plus搭建項目
- vue3
- 腳手架
- vvmily-cli
- TS
- ts筆記
- common
- Date
- utils
- axios封裝
- 2022年
- HTML
- CSS基礎
- JavaScript 基礎
- 前端框架Vue
- 計算機網絡
- 瀏覽器相關
- 性能優化
- js手寫代碼
- 前端安全
- 前端算法
- 前端構建與編譯
- 操作系統
- Node.js
- 一些開放問題、智力題