vue实现边框高度拖动
实现边框高度拖动的核心思路
通过监听鼠标事件(mousedown、mousemove、mouseup)来实现拖动效果。在Vue中结合自定义指令或组件封装更为优雅。
基础实现方案(基于自定义指令)
<template>
<div class="resizable-box" v-resize:height>
<div class="resizer"></div>
<div class="content">可拖动调整高度的区域</div>
</div>
</template>
<script>
export default {
directives: {
resize: {
inserted(el, binding) {
const direction = binding.arg || 'height'
const resizer = el.querySelector('.resizer')
resizer.style.cursor = direction === 'height' ? 'ns-resize' : 'ew-resize'
resizer.addEventListener('mousedown', initDrag)
function initDrag(e) {
e.preventDefault()
const startY = e.clientY
const startHeight = parseInt(document.defaultView.getComputedStyle(el).height, 10)
function doDrag(e) {
el.style.height = (startHeight + e.clientY - startY) + 'px'
}
function stopDrag() {
document.removeEventListener('mousemove', doDrag)
document.removeEventListener('mouseup', stopDrag)
}
document.addEventListener('mousemove', doDrag)
document.addEventListener('mouseup', stopDrag)
}
}
}
}
}
</script>
<style>
.resizable-box {
position: relative;
height: 200px;
border: 1px solid #ccc;
overflow: hidden;
}
.resizer {
position: absolute;
bottom: 0;
left: 0;
right: 0;
height: 10px;
background-color: #eee;
cursor: ns-resize;
}
.content {
padding: 10px;
}
</style>
组件化封装方案
创建可复用的ResizableBox组件:
<!-- ResizableBox.vue -->
<template>
<div class="resizable-box" :style="{ height: currentHeight + 'px' }">
<slot></slot>
<div
class="resizer"
@mousedown="startResize"
></div>
</div>
</template>
<script>
export default {
props: {
initialHeight: {
type: Number,
default: 200
}
},
data() {
return {
currentHeight: this.initialHeight,
isResizing: false
}
},
methods: {
startResize(e) {
this.isResizing = true
const startY = e.clientY
const startHeight = this.currentHeight
const doResize = (e) => {
if (!this.isResizing) return
this.currentHeight = startHeight + (e.clientY - startY)
}
const stopResize = () => {
this.isResizing = false
document.removeEventListener('mousemove', doResize)
document.removeEventListener('mouseup', stopResize)
}
document.addEventListener('mousemove', doResize)
document.addEventListener('mouseup', stopResize)
}
}
}
</script>
<style scoped>
.resizable-box {
position: relative;
border: 1px solid #ddd;
overflow: hidden;
}
.resizer {
position: absolute;
bottom: 0;
left: 0;
right: 0;
height: 8px;
background-color: #f0f0f0;
cursor: ns-resize;
transition: background-color 0.2s;
}
.resizer:hover {
background-color: #d0d0d0;
}
</style>
使用组件示例
<template>
<ResizableBox :initial-height="300">
<div class="content">
<h3>可调整高度的区域</h3>
<p>拖动底部边框调整高度</p>
</div>
</ResizableBox>
</template>
<script>
import ResizableBox from './ResizableBox.vue'
export default {
components: {
ResizableBox
}
}
</script>
进阶优化方案
添加最小/最大高度限制和拖动时的视觉反馈:
// 在ResizableBox组件的doResize方法中添加限制
doResize(e) {
if (!this.isResizing) return
let newHeight = startHeight + (e.clientY - startY)
newHeight = Math.max(this.minHeight || 50, newHeight)
newHeight = Math.min(this.maxHeight || 800, newHeight)
this.currentHeight = newHeight
}
多方向扩展方案
如果需要同时支持宽度和高度的调整:
<div class="resizer-bottom" @mousedown="startResize('height')"></div>
<div class="resizer-right" @mousedown="startResize('width')"></div>
<div class="resizer-corner" @mousedown="startResize('both')"></div>
startResize(direction) {
// 根据direction参数处理不同的拖动逻辑
}
性能优化建议
对于频繁的DOM操作,建议使用requestAnimationFrame优化:
function doResize(e) {
if (!this.isResizing) return
requestAnimationFrame(() => {
// 更新高度的逻辑
})
}






