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;
},
}
}