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 相关文章推荐
读jQuery之五(取DOM元素)
Jun 20 Javascript
使用jquery实现div的tab切换实例代码
May 27 Javascript
JavaScript解析URL参数示例代码
Aug 12 Javascript
删除条目时弹出的确认对话框
Jun 05 Javascript
JavaScript lastIndexOf方法入门实例(计算指定字符在字符串中最后一次出现的位置)
Oct 17 Javascript
jquery比较简洁的软键盘特效实现方法
Mar 19 Javascript
详解JavaScript中的表单验证
Jun 16 Javascript
TypeScript 学习笔记之基本类型
Jun 19 Javascript
jQuery增加、删除及修改select option的方法
Aug 19 Javascript
新闻上下滚动jquery 超简洁(必看篇)
Jan 21 Javascript
微信小程序自定义组件实现环形进度条
Nov 17 Javascript
vue登录注册实例详解
Sep 14 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读取本地文件常用函数(fopen与file_get_contents)
2013/09/09 PHP
php简单socket服务器客户端代码实例
2015/05/18 PHP
php生成图片验证码
2015/06/09 PHP
Yii2框架数据库简单的增删改查语法小结
2016/08/31 PHP
PHP+Mysql+Ajax实现淘宝客服或阿里旺旺聊天功能(前台页面)
2017/06/16 PHP
快速解决PHP调用Word组件DCOM权限的问题
2017/12/27 PHP
PHP使用PDO 连接与连接管理操作实例分析
2020/04/21 PHP
js中数组(Array)的排序(sort)注意事项说明
2014/01/24 Javascript
jquery实现当滑动到一定位置时固定效果
2014/06/17 Javascript
网页下载文件期间如何防止用户对网页进行其他操作
2014/06/27 Javascript
简单谈谈javascript代码复用模式
2015/01/28 Javascript
js获取字符串字节数方法小结
2015/06/09 Javascript
学习javascript面向对象 理解javascript原型和原型链
2016/01/04 Javascript
jQuery之动画效果大全
2016/11/09 Javascript
jQuery学习笔记之入门
2016/12/14 Javascript
JS中实现函数return多个返回值的实例
2017/02/21 Javascript
如何使用Bootstrap 按钮实例详解
2017/03/29 Javascript
layer弹窗插件操作方法详解
2017/05/19 Javascript
[01:55]TI9显影之尘系列 - Evil Geniuses
2019/08/22 DOTA
python 捕获 shell/bash 脚本的输出结果实例
2017/01/04 Python
python实现类之间的方法互相调用
2018/04/29 Python
Python读取mat文件,并保存为pickle格式的方法
2018/10/23 Python
pandas通过字典生成dataframe的方法步骤
2019/07/23 Python
python3实现网页版raspberry pi(树莓派)小车控制
2020/02/12 Python
Pat McGrath Labs官网:世界上最有影响力的化妆师推出的彩妆品牌
2018/01/07 全球购物
美国马匹用品和马钉购物网站:State Line Tack
2018/08/05 全球购物
澳大利亚领先的时尚内衣零售商:Bras N Things
2020/07/28 全球购物
最新的咖啡店创业计划书
2013/12/30 职场文书
网络维护中文求职信
2014/01/03 职场文书
复核员上岗演讲稿
2014/01/05 职场文书
校园之星获奖感言
2014/01/29 职场文书
《果园机器人》教学反思
2014/04/13 职场文书
青春奉献演讲稿
2014/05/08 职场文书
单位在职证明书
2014/09/11 职场文书
紧急通知
2015/04/17 职场文书
入党积极分子党支部意见
2015/06/02 职场文书