首页 >> js开发 >> jsvue模块移动组件的实现示例js大全
jsvue模块移动组件的实现示例js大全
发布时间: 2021年1月13日 | 浏览:
| 分类:js开发
一直都想实现类似于五百丁中简历填写中模块跟随鼠标移动的组件,最近闲来无事,自己琢磨实现了一个差不多的组件。其中每个模块都是组件调入(项目经验、教育经验、工作经验等),所以这里也用到了动态加载组件方式。思路:鼠标移入模块,显示相应模块的点击移动按钮,点击A模块移动按钮,此时原先A模块所在的位置上变为拖动到这里绿框模块,同时鼠标下悬浮着A模块,鼠标移动,悬浮的A模块跟随移动,绿框也跟随上下移动。父组件父组件父组件1、父组件template中的代码
v-for="(item, index) in comRoute"
:is="item"
:key="index"
@getData="getData">
ref="translateBox" v-if="transType">
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, // 获取当前组件在页面中的位置信息
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,}
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;
}
});
}
},
},
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`;
});
},
},
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();
})();
},
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);
},
},
};
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);
},
},
};
v-for="(item, index) in comRoute"
:is="item"
:key="index"
@getData="getData">
ref="translateBox" v-if="transType">
v-for="(item, index) in comRoute"
:is="item"
:key="index"
@getData="getData">
ref="translateBox" v-if="transType">
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, // 获取当前组件在页面中的位置信息
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,}
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;
}
});
}
},
},
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`;
});
},
},
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();
})();
},
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代码
@mousedown="mouseDown">
教育经验
@mousedown="mouseDown">
教育经验
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);
},
},
};
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);
},
},
};
相关文章:
- js在vue中使用防抖函数组件操作js大全
- jsElement Input输入框的使用方法js大全
- jsvue项目使用$router.go(-1)返回时刷新原来的界面操作js大全
- jsvue 页面回退mounted函数不执行的解决方案js大全
- js解决vuex数据页面刷新后初始化操作js大全
- jsAngular利用HTTP POST下载流文件的步骤记录js大全
- js解决vue动态路由异步加载import组件,加载不到module的问题js大全
- jsJS实现audio音频剪裁剪切复制播放与上传(步骤详解)js大全
- jsVue中的this.$options.data()和this.$data用法说明js大全
- js使用React-Router实现前端路由鉴权的示例代码js大全