vue拖动添加模块展示_vue模块移动组件的实现示例

一直都想实现类似于五百丁中简历填写中模块跟随鼠标移动的组件,最近闲来无事,自己琢磨实现了一个差不多的组件。

其中每个模块都是组件调入(项目经验、教育经验、工作经验等),所以这里也用到了动态加载组件方式。

思路:鼠标移入模块,显示相应模块的点击移动按钮,点击A模块移动按钮,此时原先A模块所在的位置上变为拖动到这里绿框模块,同时鼠标下悬浮着A模块,鼠标移动,悬浮的A模块跟随移动,绿框也跟随上下移动。

父组件

1、父组件template中的代码

v-for="(item, index) in comRoute"

:is="item"

:key="index"

@getData="getData">

ref="translateBox" v-if="transType">

2、data中定义的属性

comList: ['educationExp', 'workExp', 'projectExp'], // 模块列表

comLen: 0, // 模块的长度

comType: '', // 当前移动的模块

transType: '', // 当前移动的模块

coordinate: { // 鼠标坐标

mouseX: 0,

mouseY: 0,

},

downFlag: false, // 当前是否点击模块移动

mouseYBefore: 0, // 记录鼠标点击时Y坐标以及鼠标每移动30后重新记录鼠标Y坐标

mouseYLast: 0, // 实时记录鼠标移动时的Y坐标

nowCom: '', // 移动模块时,上一个模块或者下一个模块的名称

forFlage: false, // forEach遍历结束的标识

comRoute: [], // 动态加载组件列表

transCom: null, // 点击后悬浮的组件

compBox: null, // 获取当前组件在页面中的位置信息

3、scrollTop为页面滚动的距顶部的距离,从父组件传过来

props: { scrollTop: Number,}

4、watch一些属性

watch: {

comList: {

handler(val) {

this.getCom(val); // 模块列表改变时,实时加载组件

},

deep: true,

immediate: true, // 声明了之后会立马执行handler里面的函数

},

transType(val) { // 悬浮模块加载组件

if (val) {

this.transCom = () => import(`./default/${val}`);

}

},

scrollTop: { // 监听页面滚动

handler() {},

immediate: true,

},

comType(newVal) {

if (newVal) {

this.comList.forEach((item, index) => {

if (item === newVal) {

this.comList[index] = 'moveBox'; // 将组建列表中为comType的元素改为moveBox组件

}

});

this.getCom(this.comList);

}

},

downFlag(newVal) { // 鼠标已经点击

const nowThis = this;

document.onmousemove = function (e) {

if (newVal) { // 鼠标移动赋值

nowThis.coordinate.mouseX = e.clientX;

nowThis.coordinate.mouseY = e.clientY;

}

};

document.onmouseup = function () { // 鼠标松开

document.onmousemove = null;

if (newVal) {

nowThis.transType = ''; // 悬浮组件置空

nowThis.comList.forEach((item, index) => {

if (item === 'moveBox') { // 寻找moveBox所在位置

nowThis.comList[index] = nowThis.comType; // 还原成点击组件

}

});

nowThis.downFlag = false;

nowThis.comType = '';

nowThis.getCom(nowThis.comList);

}

};

},

coordinate: {

handler(newVal) { // 悬浮组件位置

this.$refs.translateBox.style.top = `${newVal.mouseY + this.scrollTop - 40 - this.compBox.y}px`;

this.$refs.translateBox.style.left = `${newVal.mouseX - this.compBox.x - 200}px`;

this.mouseYLast = newVal.mouseY;

},

deep: true,

},

mouseYLast(newVal) { // 鼠标移动Y坐标

this.forFlage = false;

if (newVal - this.mouseYBefore > 30) { // 移动30鼠标向下移,每移动30,moveBox移动一次

this.comList.forEach((item, index) => {

if (item === 'moveBox' && index < this.comLen - 1 && !this.forFlage) {

this.nowCom = this.comList[index + 1];

this.$set(this.comList, index + 1, 'moveBox');

this.$set(this.comList, index, this.nowCom);

this.mouseYBefore = newVal;

this.forFlage = true;

}

});

} else if (newVal - this.mouseYBefore < -30) { // 鼠标向上移

this.comList.forEach((item, index) => {

if (item === 'moveBox' && index > 0 && !this.forFlage) {

this.nowCom = this.comList[index - 1];

// this.comList[index - 1] = 'moveBox';

// this.comList[index] = this.nowCom;

// this.comList[index]数组中采用这种方式赋值,vue是不能检测到数组的变动的

this.$set(this.comList, index - 1, 'moveBox');

this.$set(this.comList, index, this.nowCom);

this.mouseYBefore = newVal;

this.forFlage = true;

}

});

}

},

},

其中 forFlage的作用是,在forEach中不能使用break这样来结束循环,所以用forFlage来表示,当遍历到moveBox后, 就结束遍历

5、methods

methods: {

getCom(val) {

this.comRoute = [];

val.forEach((item) => {

this.comRoute.push(() => import(`./default/${item}`));

});

},

getData(data, dataY, dataX) { // 模块组件点击后,父组件中调用此方法,并传值过来

this.comType = data;

this.transType = data; // 目前考虑点击后立即移动,点击不移动的情况后期再考虑

this.downFlag = true;

this.mouseYBefore = dataY;

this.$nextTick(() => {

this.$refs.translateBox.style.top = `${dataY + this.scrollTop - 40 - this.compBox.y}px`;

this.$refs.translateBox.style.left = `${dataX - this.compBox.x - 200}px`;

});

},

},

6、mounted

mounted() {

this.comLen = this.comList.length;

this.compBox = this.$refs.compBox.getBoundingClientRect();

const that = this;

window.onresize = () => (() => {

that.compBox = this.$refs.compBox.getBoundingClientRect();

})();

},

子组件

1、子组件template代码

教育经验

2、script

export default {

name: 'educationExp',

data() {

return {

comType: 'educationExp',

mouseYBefore: 0,

mouseXBefore: 0,

};

},

methods: {

mouseDown(e) {

this.mouseYBefore = e.clientY;

this.mouseXBefore = e.clientX;

this.$emit('getData', this.comType, this.mouseYBefore, this.mouseXBefore);

},

},

};

到此这篇关于vue模块移动组件的实现示例的文章就介绍到这了,更多相关vue模块移动组件内容请搜索脚本之家以前的文章或继续浏览下面的相关文章希望大家以后多多支持脚本之家!

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值