vue和H5 draggable實(shí)現(xiàn)拖拽并替換效果
前言
公司項(xiàng)目需要做拖拽替換效果,本人用的vue框架。在網(wǎng)上找了很多資料都是用的 Vue.Draggable(git地址)。但這個(gè)組件實(shí)現(xiàn)的拖拽后插入效果,我倒騰了很久也沒(méi)有替換效果(如果Vue.Draggable能實(shí)現(xiàn)拖拽替換效果的話請(qǐng)大神給我留言)。
JQ有實(shí)現(xiàn)拖拽的插件,我下載過(guò)一個(gè)插件并看過(guò)源碼,大致原理是給目標(biāo)元素設(shè)置定位屬性,通過(guò)監(jiān)聽(tīng)鼠標(biāo)mousedown,mouseup事件,再計(jì)算鼠標(biāo)位置變化,然后給元素樣式設(shè)置偏移值來(lái)實(shí)現(xiàn)拖拽效果的。
H5提供了專門的拖拽API 給元素添加 draggable 屬性,設(shè)置為 true就能實(shí)現(xiàn)拖拽了。本文使用的H5提供的拖拽API 以及vue 無(wú)其他任何添加,請(qǐng)放心使用
直接上代碼
<template>
<div class="container">
<div class="layout">
<button
class="layout-btn"
@click="layoutType=val.value"
v-for="val in layoutOptions"
:key="val.value"
>{{val.label}}</button>
</div>
<div
class="group"
:class="{'left-top-container': gindex===0,
'right-top-container': gindex===1,
'bottom-container': gindex===2,
'top-container': gindex<2}"
v-for="(group,gindex) in data"
:key="gindex"
>
<div
class="cls-default"
v-for="(item,cindex) in group.children"
:key="cindex"
:data-id="gindex+'-'+cindex"
draggable="true"
@dragstart="onDragstart($event)"
@dragend="onDragend($event)"
@dragover="onDragover($event)"
@drop="onDrop($event)"
:style="{'background-color': item.color}"
:class="{'cls1-0': cindex ===0 && layoutType==1,
'cls2-0': (cindex ===0 || cindex ===1) && layoutType==2,
'cls3-0': cindex ===0 && layoutType==3,
'cls3-1': (cindex ===1 || cindex ===2) && layoutType==3,
'cls4-0': cindex <4 && layoutType==4,
'cls6-0': cindex === 0 && layoutType==6
}"
>
<div class="content">{{item.color ? item.color : '我是空對(duì)象'}}</div>
</div>
</div>
<div class="tips">上面兩個(gè)區(qū)域內(nèi)是展示區(qū)的內(nèi)容能互相拖拽
<br>下面的是資源區(qū),只能復(fù)制出去覆蓋目標(biāo)區(qū)域,本身不會(huì)被替換掉
</div>
</div>
</template>
<script>
export default {
data() {
return {
stargindex: "",
endIndex: "",
layoutType: "9",
layoutOptions: [
{ label: "單分屏", value: 1 },
{ label: "二分屏", value: 2 },
{ label: "三分屏", value: 3 },
{ label: "四分屏", value: 4 },
{ label: "六分屏", value: 6 },
{ label: "九分屏", value: 9 }
],
data: [
{
group: "left-show",
title: "視頻播放區(qū)一",
children: [
{
id: 6,
color: "orange"
},
{
id: 2,
color: "yellow"
},
{},
{},
{},
{},
{
id: 3,
color: "cyan"
},
{},
{
id: 5,
color: "brown"
}
]
},
{
group: "right-show",
title: "視頻播放區(qū)二",
children: [
{},
{
id: 7,
color: "pink"
},
{},
{},
{ id: 4, color: "purple" },
{},
{},
{},
{
id: 10,
color: "gray"
}
]
},
{
group: "source",
title: "視頻資源區(qū)",
children: [
{
id: 11,
color: "white"
},
{
id: 12,
color: "black"
},
{
id: 13,
color: "red"
},
{
id: 14,
color: "green"
},
{
id: 15,
color: "blue"
}
]
}
]
};
},
methods: {
onDragstart(event) {
this.stargindex = event.target.getAttribute("data-id");
},
onDragend(event) {
let startGroupIndex = this.stargindex.split("-")[0];
let startChildIndex = this.stargindex.split("-")[1];
let endGroupIndex = this.endIndex.split("-")[0];
let endChildIndex = this.endIndex.split("-")[1];
// 對(duì)數(shù)據(jù)做簡(jiǎn)單的深拷貝 目前不需要
// let endObj = JSON.parse(
// JSON.stringify(this.data[endGroupIndex].children[endChildIndex])
// );
// let startObj = JSON.parse(
// JSON.stringify(this.data[startGroupIndex].children[startChildIndex])
// );
let endObj = this.data[endGroupIndex].children[endChildIndex];
let startObj = this.data[startGroupIndex].children[startChildIndex];
if (this.data[endGroupIndex].group === "source") {
//往資源區(qū)拖拽時(shí) 不做任何替換操作
return;
}
this.data[endGroupIndex].children.splice(endChildIndex, 1, startObj);
if (this.data[startGroupIndex].group !== "source") {
//拖拽起始區(qū)域不是 source時(shí) 把起始區(qū)域替換成拖拽后區(qū)域的數(shù)據(jù)
this.data[startGroupIndex].children.splice(startChildIndex, 1, endObj);
}
},
onDrop(event) {
if (event.target.className.indexOf("cls-default") > -1) {
this.endIndex = event.target.getAttribute("data-id");
} else {
this.endIndex = event.target.parentElement.getAttribute("data-id");
}
},
onDragover(event) {
event.preventDefault();
}
}
};
</script>
<style scoped>
.container {
background-color: #eee;
height: 800px;
}
.layout .layout-btn {
background-color: #409eff;
color: #fff;
padding: 10px 15px;
margin: 10px 15px;
}
.tips {
font-size: 24px;
text-align: center;
}
.group {
float: left;
overflow: hidden;
box-sizing: border-box;
}
.group-title {
height: 40px;
line-height: 40px;
}
.cls-default {
float: left;
margin: 0;
box-sizing: border-box;
overflow: hidden;
border: 1px solid #999;
}
.cls-default .content {
text-align: center;
padding-top: 20px;
font-size: 20px;
}
.top-container {
height: 400px;
width: 40%;
margin: 15px 5%;
}
.top-container .cls-default {
width: 33.33%;
height: 33.33%;
}
.top-container .cls1-0 {
width: 100%;
height: 100%;
}
.top-container .cls2-0 {
width: 50%;
height: 100%;
}
.top-container .cls3-0 {
width: 50%;
height: 100%;
}
.top-container .cls3-1 {
width: 50%;
height: 50%;
}
.top-container .cls4-0 {
width: 50%;
height: 50%;
}
.top-container .cls6-0 {
width: 66.66%;
height: 66.65%;
}
.bottom-container {
width: 90%;
height: 200px;
margin: 15px 5%;
}
.bottom-container .cls-default {
width: 15%;
height: 150px;
}
</style>
寫在最后
本文是我第一次寫博客,寫的比較隨意,樣式處理也是很隨心。如有錯(cuò)誤請(qǐng)指正。
后面有時(shí)間會(huì)完善組件的功能。參考Vue.Draggable(git地址)這個(gè)組件。
以上就是本文的全部?jī)?nèi)容,希望對(duì)大家的學(xué)習(xí)有所幫助,也希望大家多多支持腳本之家。
相關(guān)文章
vue中el-tab如何點(diǎn)擊不同標(biāo)簽觸發(fā)不同函數(shù)的實(shí)現(xiàn)
el-tab本身的功能是點(diǎn)擊之后切換不同頁(yè),本文主要介紹了vue中el-tab如何點(diǎn)擊不同標(biāo)簽觸發(fā)不同函數(shù)的實(shí)現(xiàn),具有一定的參考價(jià)值,感興趣的可以了解一下2024-03-03
詳解vue2.0 使用動(dòng)態(tài)組件實(shí)現(xiàn) Tab 標(biāo)簽頁(yè)切換效果(vue-cli)
本篇文章主要介紹了詳解vue2.0 使用動(dòng)態(tài)組件實(shí)現(xiàn) Tab 標(biāo)簽頁(yè)切換效果(vue-cli),具有一定的參考價(jià)值,有需要的可以了解下2017-08-08
簡(jiǎn)單了解vue中的v-if和v-show的區(qū)別
這篇文章主要介紹了簡(jiǎn)單了解vue中的v-if和v-show的區(qū)別,文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友可以參考下2019-10-10
解決VUE3 keep-alive頁(yè)面切換報(bào)錯(cuò)parentComponent.ctx.deactivate
這篇文章主要介紹了解決VUE3 keep-alive頁(yè)面切換報(bào)錯(cuò)parentComponent.ctx.deactivate is not a function的問(wèn)題,具有很好的參考價(jià)值,希望對(duì)大家有所幫助,如有錯(cuò)誤或未考慮完全的地方,望不吝賜教2023-10-10
Vue多組件倉(cāng)庫(kù)開(kāi)發(fā)與發(fā)布詳解
這篇文章主要介紹了Vue多組件倉(cāng)庫(kù)開(kāi)發(fā)與發(fā)布詳解,小編覺(jué)得挺不錯(cuò)的,現(xiàn)在分享給大家,也給大家做個(gè)參考。一起跟隨小編過(guò)來(lái)看看吧2019-02-02
vue實(shí)現(xiàn)GitHub的第三方授權(quán)方法示例
本文主要介紹了vue實(shí)現(xiàn)GitHub的第三方授權(quán),文中通過(guò)示例代碼介紹的非常詳細(xì),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下2021-11-11
一次前端Vue項(xiàng)目國(guó)際化解決方案的實(shí)戰(zhàn)記錄
這篇文章主要給大家介紹了關(guān)于前端Vue項(xiàng)目國(guó)際化解決方案的實(shí)戰(zhàn)記錄,以上只是一部分Vue項(xiàng)目開(kāi)發(fā)中遇到的典型問(wèn)題和解決方案,文中通過(guò)代碼介紹的非常詳細(xì),需要的朋友可以參考下2024-07-07

