vue+element实现拖拽分屏(主子表的形式)

实现效果:使用鼠标点击分割线拖动,可实现左右展示框宽度(也可修改为高度)的变化,如下图

1、封装组件

首先需要封装按钮点击的这条线,计算鼠标点击后滑动的距离:

<template>
  <div ref="rightResize" class="right-resize">
    <i ref="rightResizeBar">...</i>
  </div>
</template>

<script>
  export default {
    data() {
      return {
        rightAsideWidth: 300,
      }
    },
    mounted() {
      this.dragChangeRightAsideWidth();
    },
    methods: {
      dragChangeRightAsideWidth() {
	// 保留this引用
	let resize = this.$refs.rightResize;
	let resizeBar = this.$refs.rightResizeBar;
	resize.onmousedown = e => {   // 鼠标按下执行的方法
	  let startX = e.clientX;  // 记录赋值横坐标起始位置
	  // 鼠标按下颜色改变
	  resize.style.background = "#ccc";
	  resizeBar.style.background = "#aaa";
	  resize.left = resize.offsetLeft;  // 记录距离父辈元素左边缘的距离
	  document.onmousemove = e2 => {  // 鼠标移动执行的方法
	    // 计算并应用位移量
	    let endX = e2.clientX;  // 记录赋值横坐标结束的位置
	    let moveLen = startX - endX;   // 计算鼠标拖动之间的位移差
            // 如果向右拖动且最大不超过1000px,或者向左拖动且做小不小于50px ,则执行里面的方法
	    if ((moveLen < 0 && this.rightAsideWidth < 1000) || (moveLen > 0 && this.rightAsideWidth > 50)) {
	      startX = endX;  // 当前值赋值给初始值
	      this.rightAsideWidth -= moveLen;   // 侧边的宽度加(减)上拖动后的位移量,就是此时的宽度
	      if (this.rightAsideWidth < 50) {   // 设置最小宽度
		this.rightAsideWidth = 50;
	      }
	      this.$emit('input', this.rightAsideWidth);   // 需要执行的方法,可不写
              this.$emit('change', this.rightAsideWidth);// 宽度改变后 需要把宽度传给父组件
	    }
	  };
	  document.onmouseup = () => {  // 鼠标松开,样式复原
	    // 颜色恢复
	    resize.style.background = "#fafafa";
	    resizeBar.style.background = "#ccc";
	    document.onmousemove = null;
	    document.onmouseup = null;
	  };
	  return false;
        };
      }
    }
  };
</script>

<style scoped>
  .right-resize {
    width: 5px;
    height: 100%;
    cursor: w-resize;
    background: #fafafa;
  }
  .right-resize i {
    margin-top: 300px;
    width: 5px;
    height: 35px;
    display: inline-block;
    word-wrap: break-word;
    word-break: break-all;
    line-height: 8px;
    border-radius: 5px;
    background: #ccc;
    color: #888;
  }
</style>

2、父组件引用

<template>
    <div class="global-layout-vue">	
        <el-container>
            // rightAsideWidth 宽度可变化
            <el-aside v-show="leftCollapse" :style="{ width: rightAsideWidth + 'px' }"> 
		...		
            </el-aside>
	    <RightResize v-model="rightAsideWidth" @change="rightAsideWidthChange" v-show="leftCollapse"></RightResize>
            <el-main v-if="activeName == 'two'" style="padding: 0;border-left: 1px solid #dcdfe6; background-color: #eee;" class="see_main">
		...		
	    </el-main>
        </el-container>
    </div>
</template>
<script>
  export default {
        data() {
            return {
              rightAsideWidth: 300,
            }
        },
        methods: {
          rightAsideWidthChange(width) {
	      this.$store.commit('global/setRightAsideWidth', width);
          },
        }
  }
</script>

3、vuex

基础用法可参照:vuex的基础用法
1、store/index.js

import Vue from 'vue'
import Vuex from 'vuex'
import global from './modules/global'
import createPersistedState from "vuex-persistedstate"  // vuex持久化(需要安装差价插件)
Vue.use(Vuex);

export default new Vuex.Store({
    state() {
        return {
           ...
        }
        getters: {
          ...
        },
        mutations: {
          ...
        },
        modules: {
          global,
        },
        plugins: [createPersistedState({  // vuex持久化用到的参数
          storage: window.sessionStorage,
          reducer(val) {
            return val // 刷新时返回全部的vuex储存的参数
          }
        })]
});

1、store/modules/global.js

export default {
  namespaced: true,
  state: {
    rightAsideWidth: 0,
  },
  mutations: {
    setRightAsideWidth(state, rightAsideWidth) {
      state.rightAsideWidth = rightAsideWidth;
    },
  }
}
posted @ 2022-11-15 11:04  seekHelp  阅读(1585)  评论(0编辑  收藏  举报