1. 程式人生 > 程式設計 >vue模組移動元件的實現示例

vue模組移動元件的實現示例

一直都想實現類似於五百丁中簡歷填寫中模組跟隨滑鼠移動的元件,最近閒來無事,自己琢磨實現了一個差不多的元件。

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() {},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;
  },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,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模組移動元件內容請搜尋我們以前的文章或繼續瀏覽下面的相關文章希望大家以後多多支援我們!