最近在做一个vue项目,需要一个类似于easyui-layout的伸缩功能,要求可伸缩并且可拖拽,由于vue也提供了过度和动画的特性,决定利用vue提供的过渡特性自己动手写一个实现。

Vue官网对于transition组件的解释:Vue 提供了 transition 的封装组件,在下列情形中,可以给任何元素和组件添加进入/离开过渡

  • 条件渲染 (使用 v-if)

  • 条件展示 (使用 v-show)

  • 动态组件

  • 组件根节点

利用transition组件实现左侧div的伸缩隐藏,组织以下代码:

<template>
  <div id="app">
      <!-- 左侧伸缩部分 -->
      <transition name='left'>
         <div v-if='leftshow' id='leftDiv' class='layout-left'>
            this is in leftDiv
         </div>
      </transition>
      <!-- 伸缩按钮部分 -->
      <div class='layout-area'>
          <div @click='slide'>
            <span v-if='leftshow'><</span>
            <span v-if='!leftshow'>></span>
          </div>
      </div>
      <!-- 中间内容部分 -->
      <div id='centerDiv' class='layout-center'>
            this is in centerDiv
      </div>
  </div>
</template>

定义左侧伸缩部分的过渡css,过渡时间为1.5s,为了同步中间部分宽度设置中间div过渡为1.5s:

/* 过渡类 */
.left-enter,.left-leave-to{
  margin-left:-200px;
}
.left-enter-active,.left-leave-active{
  transition:1.5s;
}
...

/* 中间部分样式 */
.layout-center{
    float:right;
    background-color:gray;
    width:calc(100% - 230px);
    height:100%;
    transition:1.5s;
    border:1px solid gray;
}

通过leftshow控制左侧的显示和隐藏,左侧部分隐藏之后调整中间部分的width,:

export default {
  name: 'App',
  data:() => {
      return{
        leftshow:true,
      }
  },
  methods:{
    /*左侧伸缩隐藏*/
    slide(){
      this.leftshow = !this.leftshow;

      let leftDom = document.querySelector('#leftDiv');
      let centerDom = document.querySelector('#centerDiv');
        if(!this.leftshow){
          centerDom.style.width = 'calc(100% - 20px)';
        }else{
          centerDom.style.width = 'calc(100% - 220px)';
        }
    },
  },
}

至此,点击按钮实现伸缩功能完成:

下一步实现可拖拽:

更改template结构,添加一个可拖拽的代理div:

<template>
  <div id="app">
      <!-- 左侧伸缩部分 -->
      <transition name='left'>
         <div v-show='leftshow' id='leftDiv' class='layout-left'>
          this is in leftDiv
         </div>
      </transition>
      <!-- 伸缩按钮部分 -->
      <div class='layout-area' >
          <div @click='slide'>
            <span v-if='leftshow'><</span>
            <span v-if='!leftshow'>></span>
          </div>
      </div>
      <!-- 添加拖动代理div -->
      <div id='proxyDiv' class='layout-proxy' @mousedown.prevent='dragStart'>
        
      </div>
      <!-- 中间内容部分 -->
      <div id='centerDiv' class='layout-center'>
        this is in centerDiv
      </div>
  </div>
</template>

设置css:

/* 拖拽div */
.layout-proxy{
  position:absolute;
  cursor:w-resize;
  opacity:0;
  left:200px;
  width:10px;
  height:100%;
  background-color: blue;
}

为代理div添加鼠标按下事件事件,并且更改左侧伸缩隐藏处理:

/*左侧伸缩隐藏*/
    slide(){
      this.leftshow = !this.leftshow;
      let proxyDom = document.querySelector('#proxyDiv');
      let leftDom = document.querySelector('#leftDiv');
      let centerDom = document.querySelector('#centerDiv');
      let that = this;
        if(!this.leftshow){ //隐藏左侧div
          proxyDom.style.left = -that.layoutX + 'px';
          leftDom.style.marginLeft = -that.layoutX + 'px';
          centerDom.style.width = 'calc(100% - 20px)';
        }else{
          setTimeout(function(){
            proxyDom.style.left = that.layoutX + 'px';
            leftDom.style.marginLeft = '0px';
            centerDom.style.width = 'calc(100% - 20px - '+that.layoutX+'px)';
          },30)
          
        }
    },
    /*拖拽*/
    dragStart(e){
        let that = this;//保存this到that
        let leftDom = document.querySelector('#leftDiv');
        let centerDom = document.querySelector('#centerDiv');
        e.target.style.opacity = .8;
        /*当鼠标在拖动div按下时绑定鼠标移动事件*/
        document.onmousemove = function(event){
            e.target.style.left = event.clientX + 'px'; //拖动时更改代理div的位置,跟随鼠标运动
        }
        document.onmouseup = function(event){
          that.layoutX = event.clientX; //保存鼠标抬起的位置,
          e.target.style.opacity = 0; //代理div不可见
          leftDom.style.width = event.clientX + 'px';
          centerDom.style.width = 'calc(100% - 20px - '+event.clientX+'px)';
          //还原事件
          document.onmousemove = null;
          document.onmouseup = null;
        }
    },

拖拽效果如下:

完成代码github地址:https://github.com/jianfeng418/vue-layout

Logo

前往低代码交流专区

更多推荐