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 相关文章推荐
checkbox 复选框不能为空
Jul 11 Javascript
Jquery.LazyLoad.js修正版下载,实现图片延迟加载插件
Mar 12 Javascript
解决js中window.open弹出的是上次的缓存页面问题
Dec 29 Javascript
不使用jquery实现js打字效果示例分享
Jan 19 Javascript
JavaScript中获取Radio被选中的值
Nov 11 Javascript
javascript正则表达式总结
Feb 29 Javascript
vue2.0使用Sortable.js实现的拖拽功能示例
Feb 21 Javascript
详解angularjs利用ui-route异步加载组件
May 21 Javascript
Vue.js中轻松解决v-for执行出错的三个方案
Jun 09 Javascript
基于jQuery的左滑出现删除按钮的示例
Aug 29 jQuery
vue的mixins属性详解
Mar 14 Javascript
9种方法优化jQuery代码详解
Feb 04 jQuery
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用星号隐藏部份用户名、身份证、IP、手机号等实例
2014/04/08 PHP
php设计模式之策略模式实例分析【星际争霸游戏案例】
2020/03/26 PHP
jquery ajax提交表单数据的两种方式
2009/11/24 Javascript
Javascript学习笔记2 函数
2010/01/11 Javascript
基于Jquery的实现回车键Enter切换焦点
2010/09/14 Javascript
浅析JavaScript作用域链、执行上下文与闭包
2016/02/01 Javascript
JS针对浏览器窗口关闭事件的监听方法集锦
2016/06/24 Javascript
ionic选择多张图片上传的示例代码
2017/10/10 Javascript
Bootstrap Table 搜索框和查询功能
2017/11/30 Javascript
JS中Object对象的原型概念基础
2018/01/29 Javascript
fullpage.js最后一屏滚动方式
2018/02/06 Javascript
JavaScript实现的DOM树遍历方法详解【二叉DOM树、多叉DOM树】
2018/05/07 Javascript
详解基于Vue2.0实现的移动端弹窗(Alert, Confirm, Toast)组件
2018/08/02 Javascript
angular.js实现列表orderby排序的方法
2018/10/02 Javascript
vue.js实现回到顶部动画效果
2019/07/31 Javascript
VUE 实现动态给对象增加属性,并触发视图更新操作示例
2019/11/29 Javascript
微信小程序onShareTimeline()实现分享朋友圈
2021/01/07 Javascript
[00:58]2016年国际邀请赛勇士令状宣传片
2016/06/01 DOTA
[01:36]DOTA2完美大师赛趣味视频之与队友相处的十万个技巧
2017/11/19 DOTA
python操作xml文件示例
2014/04/07 Python
python验证码识别实例代码
2018/02/03 Python
python解决js文件utf-8编码乱码问题(推荐)
2018/05/02 Python
Python numpy.array()生成相同元素数组的示例
2018/11/12 Python
python 字段拆分详解
2019/12/17 Python
基于spring boot 日志(logback)报错的解决方式
2020/02/20 Python
Python如何用filter函数筛选数据
2020/03/05 Python
python对指定字符串逆序的6种方法(小结)
2020/04/02 Python
世界上最大的铁人三项商店:Tri UK
2020/11/04 全球购物
哈曼俄罗斯官方网上商店:Harman.club
2020/07/24 全球购物
工商管理系学生的自我评价分享
2013/11/29 职场文书
机关干部四风问题自查报告及整改措施
2014/10/26 职场文书
2014年法院个人工作总结
2014/12/17 职场文书
2015年社区居委会工作总结
2015/05/18 职场文书
关于感恩老师的古诗句
2019/08/20 职场文书
Mac M1安装mnmp (Mac+Nginx+MySQL+PHP) 开发环境
2021/03/29 PHP
Java 超详细讲解十大排序算法面试无忧
2022/04/08 Java/Android