20190826 splitPanel 简单封装

本文详细介绍了一个可拖动面板的Vue组件实现细节,包括如何响应鼠标事件调整面板宽度,以及面板宽度变化的限制和同步更新。通过计算属性和监听事件,实现了面板左、右两侧的动态宽度调整。
<!-- 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>

学到的知识

  1. box.getBoundingClientRect() 获取元素的相关属性

  2. event.srcElement 获取作用在哪个元素上

  3. <split-pannel :value=“offset” @input=“handleInput”> 父元素中的
    handleInput(value){
    this.offset = value
    }
    子元素 props: {value: {type: Number, default: “0.8”}} this.$emit(“input”,offsetPercent) ;

    这个可以缩写为

  4. .sync的用法 :value.sync=“offset”

  5. this.$emit(“update:value”,offsetPercent)

评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值