<!-- splitPannel -->
<template>
<div class="pannel-wrap" ref="outer">
<div class="pannel pannel-left" :style="{width: leftOffsetPercent}">
<slot name="left"></slot>
<!-- <button @click="handleClick">-2%</button> -->
</div>
<div class="pannel-trigger-con" :style="{left:triggerLeft, width: `${triggerWidth}px`}" @mousedown="handleMouseDown"></div>
<div class="pannel pannel-right" :style="{left: leftOffsetPercent, paddingLeft: `${triggerWidth /2 }px`}">
<slot name="right"></slot>
</div>
</div>
</template>
<script>
export default {
name: "splitPannel",
data () {
return {
canMove: false,
initOffset:0,
};
},
props:{
value:{
type: Number,
default: 0.5
},
triggerWidth: {
type: Number,
default: 8,
},
min:{
type: Number,
default: 0.1
},
max: {
type: Number,
default: 0.9
}
},
components: {},
computed:{
leftOffsetPercent(){
return `${this.value *100}%`
},
triggerLeft(){
return `calc(${this.value *100}% - ${this.triggerWidth / 2}px)`
}
},
created() {},
methods: {
handleClick(){
this.value -= 0.02;
},
handleMouseDown(event){
this.initOffset = event.pageX-event.srcElement.getBoundingClientRect().left; //鼠标距离条的偏移量
document.addEventListener("mousemove",this.handleMouseMove)
document.addEventListener("mouseup", this.handleMouseUp)
this.canMove = true
},
handleMouseMove(event){
console.log(event)
if(this.canMove){
const outerRect = this.$refs.outer.getBoundingClientRect();
let offsetPercent = (event.pageX-this.initOffset +this.triggerWidth / 2 - outerRect.left) / outerRect.width;
if(offsetPercent< this.min) offsetPercent = this.min
if(offsetPercent> this.max) offsetPercent = this.max
// this.value = offsetPercent
// this.$emit("input",offsetPercent)
this.$emit("update:value", offsetPercent)
}
},
handleMouseUp(){
this.canMove = false
}
}
}
</script>
<style lang='less' scoped>
.pannel-wrap{
width: 100%;
height: 100%;
position: relative;
.pannel{
height: 100%;
position: absolute;
top:0;
&-left{
// width: 30%;
background: palevioletred;
left:0;
}
&-right{
right:0;
// left:30%;
background: palegoldenrod;
}
&-trigger-con{
height:100%;
background-color: red;
position: absolute;
top:0;
z-index: 10;
user-select: none; //不会再元素上做选中操作
cursor: col-resize;
}
}
}
</style>
<!-- -->
<template>
<div class="wrap">
<!-- <split-pannel :value="offset" @input="handleInput"></split-pannel> -->
<!-- <split-pannel v-model="offset"></split-pannel> -->
<split-pannel :value.sync = "offset">
<div slot="left">left</div>
<div slot="right">right</div>
</split-pannel>
</div>
</template>
<script>
import splitPannel from '../../components/splitPannel.vue'
export default {
data () {
return {
offset: 0.8
};
},
components: {
splitPannel
},
created() {},
methods: {
handleInput(value){
this.offset = value
}
}
}
</script>
<style lang='less' scoped>
.wrap{
width: 600px;
height: 300px;
background-color: yellowgreen;
}
</style>
学到的知识
-
box.getBoundingClientRect() 获取元素的相关属性
-
event.srcElement 获取作用在哪个元素上
-
<split-pannel :value=“offset” @input=“handleInput”> 父元素中的
handleInput(value){
this.offset = value
}
子元素 props: {value: {type: Number, default: “0.8”}} this.$emit(“input”,offsetPercent) ;这个可以缩写为
-
.sync的用法 :value.sync=“offset”
-
this.$emit(“update:value”,offsetPercent)
本文详细介绍了一个可拖动面板的Vue组件实现细节,包括如何响应鼠标事件调整面板宽度,以及面板宽度变化的限制和同步更新。通过计算属性和监听事件,实现了面板左、右两侧的动态宽度调整。
350

被折叠的 条评论
为什么被折叠?



