小知识,大挑战!本文正在参与“程序员必备小知识”创作活动
需求:
后台管理实现一个图片列表,图片可以拖拽实现位置更改
思路:
图片列表的渲染和上传组件、拖拽组件的组合
代码:
<template>
<div class="more-img-uploade">
<draggable
:list="imgList"
tag="ul"
class="img-list"
v-bind="dragOptions"
draggable=".item"
>
<li v-for="(item, index) in imgList" :key="index" class="item">
<img :src="item.url" alt="">
<i
v-if="!canEdit"
class="el-icon-circle-close"
@click="deletImgList(index)"
/>
</li>
//图片上传到限制张数时隐藏上传图标
<li v-show="imgList.length < imgLimit" class="img-li">
<el-upload
:action="actionUrl"
:headers="headers"
:on-success="uploadSuccess"
:before-upload="uploadBefore"
class="upload-class"
:show-file-list="false"
:disabled="canEdit"
>
<i class="el-icon-plus" />
</el-upload>
</li>
</draggable>
</div>
</template>
import draggable from 'vuedraggable'
export default {
components: {
draggable
},
props: {
//上传api
actionUrl: {
type: String,
default: ''
},
//图片列表
imgList: {
type: Array,
default() {
return []
}
},
//是否可编辑
canEdit: {
type: Boolean,
default: false
},
//上传图片限制张数
imgLimit: {
type: Number,
default: 0
}
},
data() {
return {
headers: {
'api-ver': '1.0.0',
token: sessionStorage.token,
charset: 'UTF-8'
}
}
},
computed: {
// 拖拽属性
dragOptions() {
return {
animation: 200, // 动画时间
disabled: this.canEdit, // false可拖拽,true不可拖拽
group: 'description',
ghostClass: 'ghost'
}
}
},
methods: {
//上传图片进行校验
uploadBefore(file) {
// 图片格式是否正确
let bool = null
// 获取图片的后缀名
const dotIndex = file.name.lastIndexOf('.')
const suffixOfImage = file.name.slice(dotIndex + 1).toLowerCase()
switch (suffixOfImage) {
case 'gif':
case 'jpeg':
case 'png':
case 'jpg':
case 'bmp':
case 'tiff':
case 'webp':
bool = true
break
default:
bool = false
}
if (bool) {
const isLt5Mb = file.size / 1024 < 500
if (isLt5Mb) return true
else {
this.$message.warning('上传图片大小不能超过 500kb!')
return false
}
} else {
this.$message.warning('您上传的图片格式不正确!')
return false
}
},
// 上传成功
uploadSuccess(res, file, fileList) {
this.hide = true
if (res.code === 200) {
if (res.data) this.imgList.push({ url: res.data[0] })
if (res.response) this.imgList.push({ url: res.response[0] })
} else {
this.$message.warning(res.message)
}
},
// 删除图片
deletImgList(index) {
this.imgList.splice(index, 1)
}
}
}
</script>
<style lang="scss">
.more-img-uploade .el-icon-circle-close {
color: red;
position: absolute;
font-size: 15px;
z-index: 999;
right: 5px;
top: 5px;
}
</style>
<style scoped>
.img-list {
display: flex;
flex-wrap: wrap;
max-height: 350px;
overflow-y: scroll;
}
.img-list .item:nth-child(1)::after {
content: "首图";
position: absolute;
width: 40px;
height: 20px;
text-align: center;
line-height: 20px;
top: 0;
left: 0;
color: #ffffff;
font-size: 14px;
background: coral;
}
.img-list li,
.img-li {
width: 180px;
height: 120px;
margin: 15px 10px;
border: 1px dashed #d9d9d9;
border-radius: 6px;
cursor: pointer;
position: relative;
overflow: hidden;
}
.img-li {
float: left;
}
.img-list li img {
width: 100%;
height: 100%;
object-fit: contain;
background: #000;
}
.upload-class {
font-size: 28px;
color: #8c939d;
text-align: center;
height: 120px;
width: 180px;
line-height: 120px;
box-sizing: border-box;
}
</style>
vuedraggable props:
value
类型:数组,
必需:否,
默认值:null
通常与内部元素v-for指令引用的数组相同,该组件的首先使用方法,与vuex兼容,也可使用v-model
list
类型:数组,
必需:否,
默认值:null
除了上面的 value prop之外,list是一个要与拖放同步的数组。
主要的区别是list prop是由使用splice方法的draggable组件更新的,而value是不可变的,两者不能一起使用
tag
类型:字符串
默认值:div
可拖动组件创建的元素的HTML节点类型,作为包含插槽的外部元素
还可以将vue组件的名称作为元素传递。在本例中,draggable属性将传递给创建的组件
clone
类型:function
默认值:(original) => { return original;}
当克隆选项为真时,调用源组件上的函数来克隆元素。
惟一的参数是要克隆的viewModel元素,返回的值是它的克隆版本。
在默认情况下vue.draggable重用viewModel元素,所以如果您想克隆或深度克隆它,就必须使用这个钩子。
引用时:
<GlobalUploadMoreImg
:can-edit="canEdit"
:action-url="actionUrl"
:img-list.sync="imgList"
:img-limit="9"
/>