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 formValidator插件ajax验证 内容不做任何修改再离开提示错误的bug解决方法
Jan 04 Javascript
自己写的Javascript计算时间差函数
Oct 28 Javascript
jQuery实现动画效果的简单实例
Jan 27 Javascript
jquery datepicker参数介绍和示例
Apr 15 Javascript
深入理解JavaScript系列(35):设计模式之迭代器模式详解
Mar 03 Javascript
javascript实现鼠标拖动改变层大小的方法
Apr 30 Javascript
js库Modernizr的介绍和使用
May 07 Javascript
用Vue.extend构建消息提示组件的方法实例
Aug 08 Javascript
在原生不支持的旧环境中添加兼容的Object.keys实现方法
Sep 11 Javascript
微信小程序云开发之使用云函数
May 17 Javascript
基于form-data请求格式详解
Oct 29 Javascript
jQuery实现可以计算进制转换的计算器
Oct 19 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
如何给phpadmin一个保护
2006/10/09 PHP
php中ob(Output Buffer 输出缓冲)函数使用方法
2007/07/21 PHP
php使用fputcsv()函数csv文件读写数据的方法
2015/01/06 PHP
php PDO属性设置与操作方法分析
2018/12/27 PHP
实测jquery data()如何存值
2013/08/18 Javascript
在JavaScript中实现类的方式探讨
2013/08/28 Javascript
JQuery实现绚丽的横向下拉菜单
2013/12/19 Javascript
jQuery中prevAll()方法用法实例
2015/01/08 Javascript
JS对字符串编码的几种方式使用指南
2015/05/14 Javascript
jQuery插件FusionCharts实现的3D柱状图效果实例【附demo源码下载】
2017/03/03 Javascript
原生Aajax 和jQuery Ajax 写法个人总结
2017/03/24 jQuery
vue-cli history模式实现tomcat部署报404的解决方式
2019/09/06 Javascript
Vue项目中使用jsonp抓取跨域数据的方法
2019/11/10 Javascript
JS实现“全选”和&quot;全不选&quot;功能代码实例
2020/02/06 Javascript
在Vue中创建可重用的 Transition的方法
2020/06/02 Javascript
在Python中操作文件之read()方法的使用教程
2015/05/24 Python
python选择排序算法实例总结
2015/07/01 Python
利用django如何解析用户上传的excel文件
2017/07/24 Python
python模块之sys模块和序列化模块(实例讲解)
2017/09/13 Python
python 制作本地应用搜索工具
2021/02/27 Python
css3 按钮 利用css3实现超酷下载按钮
2013/03/18 HTML / CSS
lululemon美国官网:瑜伽服+跑步装备
2018/11/16 全球购物
意大利奢侈品零售商:ilDuomo Novara
2019/09/11 全球购物
Skechers越南官方网站:来自美国的运动休闲品牌
2021/02/22 全球购物
小学美术教学反思
2014/02/01 职场文书
关于运动会的稿件
2014/02/02 职场文书
春节联欢晚会主持词范文
2014/03/24 职场文书
公司聘任书模板
2014/03/29 职场文书
师范生求职信
2014/06/14 职场文书
求职信的正确写法
2014/07/10 职场文书
有关水浒传的读书笔记
2015/06/25 职场文书
莫言诺贝尔获奖感言(全文)
2015/07/31 职场文书
2015年公司中秋节致辞
2015/07/31 职场文书
golang interface判断为空nil的实现代码
2021/04/24 Golang
SpringBoot 整合mongoDB并自定义连接池的示例代码
2022/02/28 MongoDB
如何Python使用re模块实现okenizer
2022/04/30 Python