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 相关文章推荐
利用HTML5的画布Canvas实现刮刮卡效果
Sep 06 Javascript
JS模仿手机端九宫格登录功能实现代码
Apr 28 Javascript
jQuery通过ajax快速批量提交表单数据
Oct 25 Javascript
基于JS实现的随机数字抽签实例
Dec 08 Javascript
vue使用axios跨域请求数据问题详解
Oct 18 Javascript
详解如何解决vue开发请求数据跨域的问题(基于浏览器的配置解决)
Nov 12 Javascript
Three.js实现3D机房效果
Dec 30 Javascript
jQuery实现的导航条点击后高亮显示功能示例
Mar 04 jQuery
微信公众号平台接口开发 获取微信服务器IP地址方法解析
Aug 14 Javascript
实例分析JS中的相等性判断===、 ==和Object.is()
Nov 17 Javascript
基于jQuery实现可编辑的表格
Dec 11 jQuery
前端开发之便利店收银系统代码
Dec 27 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
php实现的后台表格分页功能示例
2017/10/23 PHP
laravel 5.3 单用户登录简单实现方法
2019/10/14 PHP
IE6 弹出Iframe层中的文本框“经常”无法获得输入焦点
2009/12/27 Javascript
Jquery 实现表格颜色交替变化鼠标移过颜色变化实例
2013/08/28 Javascript
使用delegate方法为一个tr标签加一个链接
2014/06/27 Javascript
基于MVC4+EasyUI的Web开发框架形成之旅之界面控件的使用
2015/12/16 Javascript
纯js实现手风琴效果
2020/04/17 Javascript
使用jQuery加载html页面到指定的div实现方法
2016/07/13 Javascript
Bootstrapvalidator校验、校验清除重置的实现代码(推荐)
2016/09/28 Javascript
利用n工具轻松管理Node.js的版本
2017/04/21 Javascript
vue基础之事件v-onclick=&quot;函数&quot;用法示例
2019/03/11 Javascript
微信小程序实现的一键连接wifi功能示例
2019/04/24 Javascript
JS实现指定区域的全屏显示功能示例
2019/04/25 Javascript
生产制造追溯系统之在线打印功能
2019/06/03 Javascript
Javascript中的this,bind和that使用实例
2019/12/05 Javascript
vue中重定向redirect:‘/index‘,不显示问题、跳转出错的完美解决
2020/09/28 Javascript
python数据结构链表之单向链表(实例讲解)
2017/07/25 Python
python获取多线程及子线程的返回值
2017/11/15 Python
PyQt5每天必学之关闭窗口
2018/04/19 Python
Python 实现使用空值进行赋值 None
2020/03/12 Python
PyCharm 在Windows的有用快捷键详解
2020/04/07 Python
Python 中如何使用 virtualenv 管理虚拟环境
2021/01/21 Python
波兰在线运动商店:YesSport
2020/07/23 全球购物
英文导游欢迎词
2014/01/11 职场文书
护士辞职信范文
2014/01/19 职场文书
《望庐山瀑布》教学反思
2014/04/22 职场文书
捐书活动总结
2014/05/04 职场文书
舞蹈教育学专业求职信
2014/06/29 职场文书
综合素质自我评价怎么写
2014/09/14 职场文书
机关领导干部作风整顿整改措施
2014/09/19 职场文书
《这片土地是神圣的》教学反思
2016/02/16 职场文书
医学会议开幕词
2016/03/03 职场文书
2019优秀干部竞聘演讲稿范文!
2019/07/02 职场文书
HTML基础-标签分类(闭合标签,空标签,块级元素,行内元素,行级块元素,可替换元素)
2021/03/31 HTML / CSS
vue完美实现el-table列宽自适应
2021/05/08 Vue.js
Python 类,对象,数据分类,函数参数传递详解
2021/09/25 Python