vue模塊移動(dòng)組件的實(shí)現(xiàn)示例
一直都想實(shí)現(xiàn)類似于五百丁中簡歷填寫中模塊跟隨鼠標(biāo)移動(dòng)的組件,最近閑來無事,自己琢磨實(shí)現(xiàn)了一個(gè)差不多的組件。

其中每個(gè)模塊都是組件調(diào)入(項(xiàng)目經(jīng)驗(yàn)、教育經(jīng)驗(yàn)、工作經(jīng)驗(yàn)等),所以這里也用到了動(dòng)態(tài)加載組件方式。
思路:鼠標(biāo)移入模塊,顯示相應(yīng)模塊的點(diǎn)擊移動(dòng)按鈕,點(diǎn)擊A模塊移動(dòng)按鈕,此時(shí)原先A模塊所在的位置上變?yōu)橥蟿?dòng)到這里綠框模塊,同時(shí)鼠標(biāo)下懸浮著A模塊,鼠標(biāo)移動(dòng),懸浮的A模塊跟隨移動(dòng),綠框也跟隨上下移動(dòng)。
父組件
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: '', // 當(dāng)前移動(dòng)的模塊
transType: '', // 當(dāng)前移動(dòng)的模塊
coordinate: { // 鼠標(biāo)坐標(biāo)
mouseX: 0,
mouseY: 0,
},
downFlag: false, // 當(dāng)前是否點(diǎn)擊模塊移動(dòng)
mouseYBefore: 0, // 記錄鼠標(biāo)點(diǎn)擊時(shí)Y坐標(biāo)以及鼠標(biāo)每移動(dòng)30后重新記錄鼠標(biāo)Y坐標(biāo)
mouseYLast: 0, // 實(shí)時(shí)記錄鼠標(biāo)移動(dòng)時(shí)的Y坐標(biāo)
nowCom: '', // 移動(dòng)模塊時(shí),上一個(gè)模塊或者下一個(gè)模塊的名稱
forFlage: false, // forEach遍歷結(jié)束的標(biāo)識(shí)
comRoute: [], // 動(dòng)態(tài)加載組件列表
transCom: null, // 點(diǎn)擊后懸浮的組件
compBox: null, // 獲取當(dāng)前組件在頁面中的位置信息
3、scrollTop為頁面滾動(dòng)的距頂部的距離,從父組件傳過來
props: { scrollTop: Number,}
4、watch一些屬性
watch: {
comList: {
handler(val) {
this.getCom(val); // 模塊列表改變時(shí),實(shí)時(shí)加載組件
},
deep: true,
immediate: true, // 聲明了之后會(huì)立馬執(zhí)行handler里面的函數(shù)
},
transType(val) { // 懸浮模塊加載組件
if (val) {
this.transCom = () => import(`./default/${val}`);
}
},
scrollTop: { // 監(jiān)聽頁面滾動(dòng)
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) { // 鼠標(biāo)已經(jīng)點(diǎn)擊
const nowThis = this;
document.onmousemove = function (e) {
if (newVal) { // 鼠標(biāo)移動(dòng)賦值
nowThis.coordinate.mouseX = e.clientX;
nowThis.coordinate.mouseY = e.clientY;
}
};
document.onmouseup = function () { // 鼠標(biāo)松開
document.onmousemove = null;
if (newVal) {
nowThis.transType = ''; // 懸浮組件置空
nowThis.comList.forEach((item, index) => {
if (item === 'moveBox') { // 尋找moveBox所在位置
nowThis.comList[index] = nowThis.comType; // 還原成點(diǎn)擊組件
}
});
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) { // 鼠標(biāo)移動(dòng)Y坐標(biāo)
this.forFlage = false;
if (newVal - this.mouseYBefore > 30) { // 移動(dòng)30鼠標(biāo)向下移,每移動(dòng)30,moveBox移動(dòng)一次
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) { // 鼠標(biāo)向上移
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]數(shù)組中采用這種方式賦值,vue是不能檢測到數(shù)組的變動(dòng)的
this.$set(this.comList, index - 1, 'moveBox');
this.$set(this.comList, index, this.nowCom);
this.mouseYBefore = newVal;
this.forFlage = true;
}
});
}
},
},
其中 forFlage的作用是,在forEach中不能使用break這樣來結(jié)束循環(huán),所以用forFlage來表示,當(dāng)遍歷到moveBox后, 就結(jié)束遍歷
5、methods
methods: {
getCom(val) {
this.comRoute = [];
val.forEach((item) => {
this.comRoute.push(() => import(`./default/${item}`));
});
},
getData(data, dataY, dataX) { // 模塊組件點(diǎn)擊后,父組件中調(diào)用此方法,并傳值過來
this.comType = data;
this.transType = data; // 目前考慮點(diǎn)擊后立即移動(dòng),點(diǎn)擊不移動(dòng)的情況后期再考慮
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> 教育經(jīng)驗(yàn) </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);
},
},
};
到此這篇關(guān)于vue模塊移動(dòng)組件的實(shí)現(xiàn)示例的文章就介紹到這了,更多相關(guān)vue模塊移動(dòng)組件內(nèi)容請(qǐng)搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
相關(guān)文章
vue中關(guān)于element的el-image 圖片預(yù)覽功能增加一個(gè)下載按鈕(操作方法)
這篇文章主要介紹了vue中關(guān)于element的el-image 圖片預(yù)覽功能增加一個(gè)下載按鈕,本文通過實(shí)例代碼給大家介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或工作具有一定的參考借鑒價(jià)值,需要的朋友可以參考下2023-04-04
vue3 elementPlus 表格實(shí)現(xiàn)行列拖拽及列檢索功能(完整代碼)
本文通過實(shí)例代碼給大家介紹vue3 elementPlus 表格實(shí)現(xiàn)行列拖拽及列檢索功能,代碼簡單易懂,對(duì)大家的學(xué)習(xí)或工作具有一定的參考借鑒價(jià)值,需要的朋友參考下吧2023-10-10
vue中接口域名配置為全局變量的實(shí)現(xiàn)方法
今天小編就為大家分享一篇vue中接口域名配置為全局變量的實(shí)現(xiàn)方法,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。一起跟隨小編過來看看吧2018-09-09

