先上效果图,里面的球都可以拖动,也可以添加,都会有对应的函数,都是用原生js做的.其实我更推荐使用
<template>
<div class="bluebox" :style="{ width: `${(row + 1) * 35}px`, height: `${(cols + 1) * 34}px` }">
<div :style="{ marginLeft: '32px', width: `${(row + 1) * 34}px` }">
<div class="topnum" v-for="item in row" :key="item">
{{ item }}
</div>
</div>
<div style="display: flex">
<div>
<div class="leftnum" v-for="item in cols" :key="item">
{{ item }}
</div>
</div>
<div>
<div v-for="ai in cols" :key="ai" style="height: 32px; margin-bottom: 1px; display: flex">
<div @drop="end" class="sonbox" v-for="item in row" :key="item" @dragenter="(event) => event.preventDefault()"
@dragover="(event) => event.preventDefault()">
<div @click="rollShow(data[(ai - 1) * row + item - 1])" :draggable="draggable" @drop="drop"
@dragstart="handleDragStart($event, items)" class="sphere dragbox"
v-show="data[(ai - 1) * row + item - 1]?.isshow" :style="{
backgroundColor: data[(ai - 1) * row + item - 1]?.strainIndex >= 0 ? '#d7d7d7' : '',
}">
<span style="font-size: 0">{{ data[(ai - 1) * row + item - 1]?.text }}</span>
</div>
</div>
</div>
</div>
</div>
</div>
</template>
<script setup>
import { ref, reactive, defineEmits, watch, defineExpose } from 'vue';
const emit = defineEmits(['endDraggable', 'rollShow']);
const data = ref([]);
const props = defineProps({
row: { type: Number, default: 10 },
cols: { type: Number, default: 10 },
list: {
type: Array,
default: [],
},
//true是允许 false是禁止
draggable: { type: Boolean, default: false },
});
for (let index = 0; index < 100; index++) {
data.value.push({
text: index,
isshow: false,
});
}
const rest = () => {
data.value = []
for (let index = 0; index < 100; index++) {
data.value.push({
text: index,
isshow: false,
});
}
};
const drop = (e) => {
e.preventDefault();
};
const updata = () => {
rest();
props.list.forEach((item) => {
item.text = item.sortIndex;
item.isshow = true;
data.value[item.sortIndex] = item;
});
let num = data.value.findIndex((item) => item == undefined);
};
watch(
() => props.list.length,
(val, prevVal) => {
updata();
},
);
//获取点击蓝色球的数据
const rollShow = (data) => {
// 把数据在多少行返回出去
emit(
'rollShow',
props.list.findIndex((item) => item.id == data.id),
);
};
let dragging = reactive();
const handleDragStart = (e, items) => {
if (!props.draggable || data.value[e.target.lastChild.textContent]?.strainIndex >= 0) return;
dragging = e.target.lastChild.textContent; //开始拖动时,暂时保存当前拖动的数据。
};
const end = (e) => {
if (!props.draggable || !dragging || data.value[e.target.lastChild.textContent]?.strainIndex >= 0) return (dragging = null);
const text = Number(e.target.lastChild.textContent);
dragging = Number(dragging);
if (text == dragging) return;
let change = { ...data.value[text] };
data.value[text] = data.value[dragging];
data.value[text].text = text;
data.value[dragging] = change;
data.value[dragging].text = dragging;
emit('endDraggable', [dragging, text]);
dragging = '';
};
</script>
<style lang="less" scoped>
.bluebox {
border: 1px solid skyblue;
.topnum {
height: 30px;
width: 30px;
display: inline-block;
text-align: center;
margin: 0 3px 3px 0;
line-height: 30px;
}
.leftnum {
height: 32px;
width: 30px;
text-align: center;
margin: 0 0 1px 0;
line-height: 30px;
}
.sonbox {
height: 30px;
width: 30px;
display: inline-block;
background-color: #efefef;
margin: 0 3px 0 0;
.sphere {
height: 30px;
width: 30px;
border-radius: 15px;
background-color: skyblue;
}
}
}
.dragbox[dragging] {
height: 30px;
width: 30px;
border-radius: 15px;
background-color: skyblue;
}
.dropbox[over] {
display: none;
}
</style>
数组里面的对象需要有sortIndex,这个是用来定位的