封装的组件的代码:
<template>
<div>
<!-- 该组件专门用于:用于上传图片(预览、上传、删除)-->
<!-- 他的接口现在只能一次上传一个-->
<!-- :getPopupContainer="triggerNode => triggerNode.parentNode" 这个属性是写个下拉菜单的,为了让展开的下拉框可以随着页面滚动跟着动-->
<!-- 本组件一般放在 CreateForm中,上传logo。故createForm即为所称“父组件” -->
<!-- 本组件:通过 this.$emit('upload', file, fileList) 给父组件传递数据 -->
<!-- 父组件:需要触发 @upload='getUpload' 收到子组件传来的fileList -->
<!-- getUpload(file, fileList){
console.log('父亲收到图片组件传来的fileList',fileList);
this.fileList= fileList
}, -->
<!-- 本组件:须接受父组件传递 FileList -->
<!-- 父组件:<UploadPicture @upload='getUpload' :FileList='fileList'></UploadPicture> -->
<a-upload
class="upload-list-inline"
ref="uploader"
list-type="picture-card"
:fileList="FileList"
:before-upload="beforeUpload"
:custom-request="() => {}"
:remove="handleRemove"
@change="handleChange"
@preview="handlePreview"
:multiple="multiple"
>
<!-- 单图片上传开启这个 -->
<div v-if="FileList.length < 1">
<a-icon type="plus" />
<div class="ant-upload-text">上传</div>
</div>
<!-- 多图片上传 -->
<!-- <div>
<a-icon type="plus" />
<div class="ant-upload-text">上传</div>
</div> -->
</a-upload>
<!-- <a-modal :visible="true" :footer="null" @cancel="handleCancel">
<img alt="example" style="width: 100%" :src="previewImage" />
</a-modal> -->
<image-viewer
v-if="previewVisible"
:url-list="[previewImage]"
:on-close="
() => {
previewVisible = false
}
"
/>
</div>
</template>
<script>
//这里需要引入 图片 处理方法
import { getBase64 } from '@/getBase64'
export default {
name: 'UploadPicture',
data() {
return {
fileList: [],
previewVisible: false,
previewImage: '',
}
},
props: {
// 增加控制是否是多选文件的字段
multiple: {
type: Boolean,
default: false,
},
// 接受父组件传递的对象
FileList: {
type: Array,
default: () => [],
},
},
methods: {
// 预览图片(点开小眼睛)
async handlePreview(file) {
console.log('11', file)
if (!file.url && !file.preview) {
file.preview = await getBase64(file.originFileObj)
}
this.previewImage = file.url || file.preview
this.previewVisible = true
},
// 取消预览图片
handleCancel() {
this.previewVisible = false
},
// 上传附件
handleChange({ file, fileList }) {
// 在上传发生变化后,将获得的文件对象提交
// 判断,如果是多文件上传,则提交文件数组,如果是单文件则提交单文件
// 这个函数默认被传入的两个参数 file, fileList,分别为触发这一次change事件时添加的原始文件对象,和已上传的全部文件数组
// file 当前操作的文件对象,fileList 当前的文件列表。
// 只保留一个文件
if (fileList.length > 1) {
fileList.splice(0, 1)
}
this.fileList = fileList
console.log('$emitupload图片组件给父亲传file、fileList', file, fileList)
this.$emit(
'upload',
file,
fileList
)
},
// 删除图片
handleRemove(file) {
this.$emit('remove', file)
},
// 上传文件之前的钩子,参数上传的文件
beforeUpload(file, fileList) {
const testmsg = /^image\/(jpeg|png|jpg)$/.test(file.type)
const isLt10M = file.size / 1024 / 1024 <= 10 // 图片大小不超过10MB
if (!testmsg) {
this.$message.error('上传图片格式不对!')
return Promise.reject(new Error(false))
}
if (!isLt10M) {
this.$message.error('上传图片大小不能超过 10M!')
return Promise.reject(new Error(false))
}
return false
},
handleUpload() {
console.log('handleUpload', this.fileList)
const { fileList } = this
const formData = new FormData()
fileList.forEach((file) => {
formData.append('files[]', file)
})
this.uploading = true
},
},
}
</script>
<style scoped lang='less'>
</style>
图片处理方法方法封装:getBase64.js
export const getBase64 = file => {
return new Promise((resolve, reject) => {
const reader = new FileReader()
reader.readAsDataURL(file)
reader.onload = () => resolve(reader.result)
reader.onerror = error => reject(error)
})
}
父组件中:需要传递FileList(props);需要接收子组件传递的fileList($emit)
<template>
<a-modal
:title="title"
:width="640"
:visible="visible"
:confirmLoading="loading"
@ok="() => { $emit('ok', $refs.ruleForm, fileList) }"
@cancel="() => { $emit('cancel') }"
okText="确定"
cancelText="取消"
>
<a-spin :spinning="loading">
<a-form-model
ref="ruleForm"
:labelCol="labelCol.sm"
:wrapperCol="wrapperCol.sm"
:model="form"
:rules="rules"
>
<a-form-model-item ref="username" label="账号" prop="username">
<a-input v-model="form.username" placeholder="请输入用户名称" allowClear :disabled="model && Object.keys(model).length > 0"/>
<a-alert message="新建账号默认密码为 admin123,可以在登录后进行重置。" banner v-if="!model"/>
</a-form-model-item>
<a-form-model-item ref="showname" label="名称" prop="showname">
<a-input v-model="form.showname" placeholder="请输入显示名称" allowClear/>
</a-form-model-item>
<a-form-model-item ref="sex" label="性别" prop="sex">
<a-radio-group default-value="男" button-style="solid" v-model="form.sex">
<a-radio-button value="男">
男
</a-radio-button>
<a-radio-button value="女">
女
</a-radio-button>
<!-- <a-radio-button value="?">-->
<!-- ?-->
<!-- </a-radio-button>-->
</a-radio-group>
</a-form-model-item>
<a-form-model-item ref="phone_number" label="电话" prop="phone_number">
<a-input v-model="form.phone_number" placeholder="请输入联系电话" allowClear/>
</a-form-model-item>
<a-form-model-item ref="email" label="邮箱" prop="email">
<a-input v-model="form.email" placeholder="请输入邮箱" allowClear/>
</a-form-model-item>
<a-form-model-item label="LOGO">
<UploadPicture @upload='getUpload' :FileList='fileList'></UploadPicture>
</a-form-model-item>
</a-form-model>
</a-spin>
</a-modal>
</template>
<script>
//这里根据自己的封装组件位置进行引入
import UploadPicture from '@/UploadPicture/UploadPicture'
import {
validatorEmail
} from '@/validate'
const originForm = {
username: '',
showname: '',
phoneNumber: '',
email: '',
sex: '男'
}
export default {
name:'son',
components: {
UploadPicture
},
props: {
visible: {
type: Boolean,
required: true
},
loading: {
type: Boolean,
default: () => false
},
model: {
type: Object,
default: () => null
}
},
data () {
this.originForm = originForm
return {
labelCol: {
xs: { span: 24 },
sm: { span: 7 }
},
wrapperCol: {
xs: { span: 24 },
sm: { span: 13 }
},
title: '新增',
fileList: [],
previewVisible: false,
previewImage: '',
form: originForm,
rules: {
username: [
{ required: true, message: '请输入账户名称', trigger: 'blur' },
{ min: 1, max: 20, message: '长度必须为 1 - 20 个字', trigger: 'blur' }
],
showname: [
{ required: true, message: '请输入显示名称', trigger: 'blur' },
{ min: 1, max: 16, message: '长度必须为 1 - 16 个字', trigger: 'blur' }
],
sex: [
{ required: true, message: '请选择性别', trigger: 'blur' }
],
email: [
{ required: true, validator: validatorEmail, trigger: 'blur' }
],
phone_number: [
{ required: true, message: '请填写电话号码', trigger: 'blur' }
// { required: true, validator: validatorPhone, trigger: 'blur' }
]
},
aa:'',
uploading: false
}
},
created () {
console.log('custom modal created', this.model)
// 当 model 发生改变时,为表单设置值
this.$watch('model', val => {
if (val && Object.keys(val).length > 0) {
this.form = { ...val }
this.title = '编辑'
if (val.logo) {
this.fileList = [{
uid: '-1',
name: 'image.png',
status: 'done',
url: val.logo
}]
} else {
this.fileList = []
}
this.$nextTick(() => {
this.$refs.ruleForm.clearValidate()
})
} else {
this.form = { ...originForm }
this.title = '新增'
this.fileList = []
this.$nextTick(() => {
// this.$refs.ruleForm.resetFields()
this.$refs.ruleForm.clearValidate()
})
}
})
},
methods: {
// 收到子组件传来的fileList
getUpload(file, fileList){
// console.log('父亲收到图片组件传来的fileList',fileList);
this.fileList= fileList
},
}
}
</script>