vue 图片添加,删除、拖拽排序

目的:现有一个图片的列表,拖动其中一个图片(触发dragstart),当拖动的图片移动到其他图片的位置(触发dragover),则将拖动的图片从原位置移动到该位置(触发dragend)。

dragstart:当用户开始拖动一个元素 dragstart 事件就会触发,事件源是该元素。

dragover:被拖拽元素经过时触发 dragover 事件(每几百毫秒触发一次)。

dragend:拖放事件在拖放操作结束时触发,事件源是拖动元素(和dragstart的事件源是同一个元素)。

事件文档:dragstart - Web API 接口参考 | MDN

效果:

实现组件:

<template>
	<div>
		<ul class='img-wrapper' 
            @dragstart="onDragStart" 
            @dragover="onDragOver"
            @dragend="onDragEnd">
			<li class="img-box" 
                v-for="(url,index) in imgList" :key='url+index'>
				<img :src="url" draggable="true">
				<i @click="remove_img(index)" class="clear"></i>
			</li>
			<div class="img-box logo-empty"
                 v-if="imgList.length!==count" 
                 @click="addImage">
            </div>
		</ul>
		<div class="tip">图片宽高要求1:1比例,建议尺寸为640px*640px以上;最多上传5张图片,您可以拖拽图片调整图片顺序。</div>
	</div>
</template>

<script setup>
	import { toRefs } from 'vue'
	const props = defineProps({
		imgList: {
			required: true,
			type: Array,
			default: []
		},
		count: {
			required: true,
			type: Number,
			default: 5
		},
		change: {
			required: true,
			type: Function,
			default () {
				return 'Default function'
			}
		},
		addImage: {
			required: true,
			type: Function,
			default () {
				return 'Default function'
			}
		}
	})
	let target = undefined;
	const { imgList, count, change } = toRefs(props);

	function onDragStart(event) {

	}

	function onDragOver(event) {
		event.preventDefault();
		let hoverEle = event.target || event.srcElement;
		hoverEle.src && (target = hoverEle)
	}

	function onDragEnd(event) {
		let draging = event.target || event.srcElement;
		if (target.src && draging.src && draging.src!==target.src) {			
			let dragingIndxe = imgList.value.indexOf(draging.src)
			let targetIndex = imgList.value.indexOf(target.src)
			change.value(dragingIndxe, 1, target.src)
			change.value(targetIndex, 1, draging.src)
		}
	}

	function remove_img(index) {
		change.value(index, 1);
	}
</script>

<style lang="scss" scoped>
	@import "@/assets/style/common.scss";

	.tip {
		color: #999;
	}

	.img-wrapper {
		display: flex;
		width: 80%;
		cursor: pointer;

		.img-box {
			position: relative;
			height: $px120;
			width: $px120;
			border-radius: $px5;
			margin-right: $px12;
			border: 1px solid #dcdfe6;

			img {
				width: 100%;
				height: 100%;
				border-radius: $px5;
			}

			.clear {
				position: absolute;
				top: -$px12;
				right: -$px12;
				height: $px24;
				width: $px24;
				border-radius: 50%;
				background-color: #d7d7d7;

				&::after {
					position: absolute;
					top: calc(50% - $px10);
					left: calc(50% - $px1);
					display: block;
					content: "";
					width: $px2;
					height: $px20;
					background-color: #fff;
					transform: rotate(-45deg)
				}

				&::before {
					position: absolute;
					top: calc(50% - $px10);
					right: calc(50% - $px1);
					display: block;
					content: "";
					width: $px2;
					height: $px20;
					background-color: #fff;
					transform: rotate(45deg)
				}

				&:hover {
					background-color: red;

					&::before {
						background-color: #fff;
					}

					&::after {
						background-color: #fff;
					}
				}
			}
		}

		.logo-empty {
			box-sizing: border-box;
			border: $px1 solid #dcdfe6;
			position: relative;

			&::before {
				position: absolute;
				top: calc(50% - $px2);
				left: calc(50% - $px20);
				display: block;
				content: "";
				height: $px4;
				width: $px40;
				background-color: $placeholder;
			}

			&::after {
				position: absolute;
				top: calc(50% - $px20);
				right: calc(50% - $px2);
				display: block;
				content: "";
				height: $px40;
				width: $px4;
				background-color: $placeholder;
			}

			&:hover {
				background-color: #C9C9C9;

				&::before {
					background-color: #fff;
				}

				&::after {
					background-color: #fff;
				}
			}
		}
	}
</style>

组件使用:

<template>
	<div>
		<imglist :imgList="imgs" 
		:count="5" 
		:change="change" 
		:addImage="addImage"></imglist>
	</div>
</template>

<script setup>
	import {ref} from "vue"
	import imglist from "@/components/imgList.vue"
	const imgs =ref([]);
	function change(){
		imgs.value.splice(...arguments)
	}
	let imgpath=[
		"https://gimg2.baidu.com/image_search/src=http%3A%2F%2Fimg.jj20.com%2Fup%2Fallimg%2F1114%2F0G020114924%2F200G0114924-1-1200.jpg&refer=http%3A%2F%2Fimg.jj20.com&app=2002&size=f9999,10000&q=a80&n=0&g=0n&fmt=auto?sec=1658730246&t=e46ec7fddbc22b7749934cecee37f497",
		"https://gimg2.baidu.com/image_search/src=http%3A%2F%2Fimg.jj20.com%2Fup%2Fallimg%2Ftp09%2F21031FKU44S6-0-lp.jpg&refer=http%3A%2F%2Fimg.jj20.com&app=2002&size=f9999,10000&q=a80&n=0&g=0n&fmt=auto?sec=1658730246&t=b3a3d686af67c6b9832d26a54f088862",
		"https://gimg2.baidu.com/image_search/src=http%3A%2F%2Fimg.jj20.com%2Fup%2Fallimg%2F4k%2Fs%2F02%2F2109242306111155-0-lp.jpg&refer=http%3A%2F%2Fimg.jj20.com&app=2002&size=f9999,10000&q=a80&n=0&g=0n&fmt=auto?sec=1658730246&t=2d9022c5f303614fc15ccab2eb0b4267",
		"https://gimg2.baidu.com/image_search/src=http%3A%2F%2Fimg.jj20.com%2Fup%2Fallimg%2F1113%2F0F420110430%2F200F4110430-6-1200.jpg&refer=http%3A%2F%2Fimg.jj20.com&app=2002&size=f9999,10000&q=a80&n=0&g=0n&fmt=auto?sec=1658730246&t=3d81803a13b4be2bae79bf4dc4b86819",
		"https://gimg2.baidu.com/image_search/src=http%3A%2F%2Fimg.jj20.com%2Fup%2Fallimg%2F1114%2F0G020114924%2F200G0114924-15-1200.jpg&refer=http%3A%2F%2Fimg.jj20.com&app=2002&size=f9999,10000&q=a80&n=0&g=0n&fmt=auto?sec=1658730246&t=001736fa40c669dc49bfc182f095bd7c"];
	function addImage(){
		imgs.value.push(imgpath[imgs.value.length])
	}
</script>

<style>
</style>

  • 0
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值