vue模块移动组件的实现示例


Posted in Javascript onMay 20, 2020

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

vue模块移动组件的实现示例

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

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

父组件

1、父组件template中的代码

<div class="component-box" ref="compBox">
 <component
   v-for="(item, index) in comRoute"
   :is="item"
   :key="index"
   @getData="getData">
</component>
 <div :class="['translate-box', {'move-icon':transType}]"
    ref="translateBox" v-if="transType">
  <component :is="transCom"></component>
 </div>
</div>

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代码

<div class="pad-box hover-box name-box">
 <p class="absolute-box">
  <i class="el-icon-rank operation-icon move-icon"    @mousedown="mouseDown"></i>
  <i class="el-icon-circle-plus operation-icon"></i>
  <i class="el-icon-s-tools operation-icon"></i>
 </p>
 教育经验
</div>

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模块移动组件内容请搜索三水点靠木以前的文章或继续浏览下面的相关文章希望大家以后多多支持三水点靠木!

Javascript 相关文章推荐
javascript实现仿银行密码输入框效果的代码
Dec 13 Javascript
纯javascript实现自动发送邮件
Oct 21 Javascript
jsonp跨域请求数据实现手机号码查询实例分析
Dec 12 Javascript
JavaScript如何实现跨域请求
Aug 05 Javascript
AngularJS中transclude用法详解
Nov 03 Javascript
jQuery插件HighCharts绘制的基本折线图效果示例【附demo源码下载】
Mar 07 Javascript
详解Vue2 无限级分类(添加,删除,修改)
Mar 07 Javascript
js如何获取网页所有图片
May 12 Javascript
基于Vue制作组织架构树组件
Dec 06 Javascript
javascript数据结构之多叉树经典操作示例【创建、添加、遍历、移除等】
Aug 01 Javascript
VUE渲染后端返回含有script标签的html字符串示例
Oct 28 Javascript
原生js实现瀑布流效果
Mar 09 Javascript
vue父子组件间引用之$parent、$children
May 20 #Javascript
jQuery HTML获取内容和属性操作实例分析
May 20 #jQuery
微信小程序国际化探索实现(附源码地址)
May 20 #Javascript
jQuery HTML设置内容和属性操作实例分析
May 20 #jQuery
jquery html添加元素/删除元素操作实例详解
May 20 #jQuery
jQuery HTML css()方法与css类实例详解
May 20 #jQuery
15分钟上手vue3.0(小结)
May 20 #Javascript
You might like
redis 队列操作的例子(php)
2012/04/12 PHP
在Mac OS的PHP环境下安装配置MemCache的全过程解析
2016/02/15 PHP
浅谈php fopen下载远程文件的函数
2016/11/18 PHP
利用JS重写Cognos右键菜单的实现代码
2010/04/11 Javascript
Dom 结点创建 基础知识
2011/10/01 Javascript
深入理解JavaScript系列(13) This? Yes,this!
2012/01/18 Javascript
JavaScript高级程序设计 阅读笔记(十八) js跨平台的事件
2012/08/14 Javascript
深入理解javaScript中的事件驱动
2013/05/21 Javascript
js/jquery判断浏览器的方法小结
2014/09/02 Javascript
js 获取元素在页面上的偏移量的方法汇总
2015/04/13 Javascript
js淡入淡出焦点图幻灯片效果代码分享
2015/09/08 Javascript
JavaScript使用Range调色及透明度实例
2016/09/25 Javascript
js中删除数组中的某一元素实例(无下标时)
2017/02/28 Javascript
前端开发之CSS原理详解
2017/03/11 Javascript
jquery Form轻松实现文件上传
2017/05/24 jQuery
使用travis-ci如何持续部署node.js应用详解
2017/07/30 Javascript
BootStrap数据表格实例代码
2017/09/13 Javascript
vue2.0使用v-for循环制作多级嵌套菜单栏
2018/06/25 Javascript
解决vue-cli3 使用子目录部署问题
2018/07/19 Javascript
Vue2.x通用条件搜索组件的封装及应用详解
2019/05/28 Javascript
JS如何实现封装列表右滑动删除收藏按钮
2020/07/23 Javascript
JS中队列和双端队列实现及应用详解
2020/09/29 Javascript
原生js实现自定义滚动条组件
2021/01/20 Javascript
Python 时间处理datetime实例
2008/09/06 Python
Python字典简介以及用法详解
2016/11/15 Python
python调用Delphi写的Dll代码示例
2017/12/05 Python
python监控进程脚本
2018/04/12 Python
python定时关机小脚本
2018/06/20 Python
对python中字典keys,values,items的使用详解
2019/02/03 Python
Numpy 中的矩阵求逆实例
2019/08/26 Python
夜大自我鉴定
2013/10/31 职场文书
测试工程师职业规划书
2014/02/06 职场文书
商务英语专业求职信
2014/06/26 职场文书
机动车登记业务委托书
2014/10/08 职场文书
Pandas搭配lambda组合使用详解
2022/01/22 Python
解决Oracle数据库用户密码过期
2022/05/11 Oracle