一、upload上传文件及表单,且显示列表(单个)
功能:1、上传文件校验 2、随表单一块提交 3、文件列表展示 4、列表删除后文件联动
效果图:
代码:
父组件:
<template>
<div class="form-page">
<el-button @click="addItem">新建</el-button>
<!-- <el-button @click="addItem">编辑</el-button>-->
<!--新建-->
<newEditForm ref="addForm" :dialogVisible.sync="dialogVisible" @save="save"></newEditForm>
</div>
</template>
<script>
import newEditForm from '../components/formDialog7'
export default {
name: "formDemo7",
data() {
return {
dialogVisible: false
}
},
components: {
newEditForm
},
methods: {
addItem() {
this.dialogVisible = true;
this.$nextTick(() => {
this.$refs.addForm.resetForm();
})
},
save(data) {
console.log(data);
}
}
}
</script>
<style lang="less" scoped>
.formDemo-page {
text-align: left;
}
</style>
子组件:
<template>
<!--功能(单个文件):1、上传文件校验 2、随表单一块提交 3、文件列表展示 4、列表删除后文件联动 -->
<el-dialog
title="提示"
:visible="dialogVisible"
:close-on-click-modal="false"
:close-on-press-escape="false"
@update:visible="changeVisible()"
width="30%">
<el-form ref="form" :model="form" label-width="80px" :rules="rules">
<el-form-item label="名称" prop="name">
<el-input v-model="form.name"></el-input>
</el-form-item>
<el-form-item label="上传文件" prop="file">
<el-upload
class="upload-demo"
drag
action=""
accept=".txt,.jpg"
:on-change="handleChange"
:auto-upload="false"
:file-list="form.file"
:on-remove="handleAddRemove"
>
<i class="el-icon-upload"></i>
<div class="el-upload__text">将文件拖到此处,或<em>点击上传</em></div>
<div class="el-upload__tip" slot="tip">只能上传txt/jpg文件,且不超过5kb</div>
</el-upload>
</el-form-item>
</el-form>
<span slot="footer" class="dialog-footer">
<el-button @click="changeVisible()">取 消</el-button>
<el-button type="primary" @click="save()">确 定</el-button>
</span>
</el-dialog>
</template>
<script>
export default {
name: "formDialog7",
props: ['dialogVisible'],
data() {
return {
form: {
name: '',
file: []
},
rules: {
name: [{required: true, message: '请输入名称', trigger: 'blur'}],
file: [{required: true, validator: this.validateFile}],
}
}
},
methods: {
resetForm() {
this.$refs.form.resetFields();
},
// 取消
changeVisible(value = false) {
this.$emit('update:dialogVisible', value)
},
// 改变文件
handleChange(file, fileList) {
// 个人理解:this.form.file是已有列表,fileList是已有列表加上新加的文件,需手动赋值处理;
// 如果不处理,已有列表会自动显示fileList(检测到this.form.file变化就显示this.form.file,否则显示fileList)
this.form.file = [file];
this.$refs.form.validateField('file', (err) => {
if (err) {
//文件校验不通过,列表删除最后一个
this.form.file = fileList;
this.form.file.splice(-1, 1);
}
});
},
//移除文件
handleAddRemove(file, fileList) {
//仅支持单个文件时
this.form.file = fileList;
},
save() {
if (!this.validate()) return;
this.$emit('save', this.form)
},
// 自定义文件校验规则
validateFile(rule, value, callback) {
let file = this.form.file[0];
if (!file) {
callback(new Error('请上传文件'));
return false;
}
//file格式及大小校验
const validName = file.name.endsWith('.txt') || file.name.endsWith('.jpg');
const validSize = file.size < (1024 * 5);
if (!validName) {
callback(new Error('文件类型不正确'));
} else if (!validSize) {
callback(new Error('文件大小超出限制'));
} else {
callback();
}
},
validate() {
let result = false;
this.$refs.form.validate((valid) => {
result = valid;
})
return result;
}
}
}
</script>
<style lang="less" scoped>
</style>
before-upload和auto-upload是互斥的,当auto-upload是false的时候,before-upload事件是没作用的,所以使用on-change事件来代替。
二、upload上传文件及表单,且显示列表(多个)
功能(多个文件): 1、上传文件校验 2、随表单一块提交 3、文件列表展示 4、列表删除后文件联动5、支持多个文件上传且分别校验 6、去掉列表展示的动画效果
效果:
父组件:
<template>
<div class="form-page">
<el-button @click="addItem">新建</el-button>
<!--新建-->
<newEditForm ref="addForm" :dialogVisible.sync="dialogVisible" @save="save"></newEditForm>
</div>
</template>
<script>
import newEditForm from '../components/formDialog7-1'
export default {
name: "formDemo7-1",
data() {
return {
dialogVisible: false
}
},
components: {
newEditForm
},
methods: {
addItem() {
this.dialogVisible = true;
this.$nextTick(() => {
this.$refs.addForm.resetForm();
})
},
save(data) {
console.log(data);
}
}
}
</script>
<style lang="less" scoped>
.formDemo-page {
text-align: left;
}
</style>
子组件:
<template>
<div class="formDialog7-1">
<!--功能(多个文件):1、上传文件校验 2、随表单一块提交 3、文件列表展示 4、列表删除后文件联动
5、支持多个文件上传且分别校验 6、去掉列表展示的动画效果-->
<el-dialog
title="提示"
:visible="dialogVisible"
:close-on-click-modal="false"
:close-on-press-escape="false"
@update:visible="changeVisible()"
width="30%">
<el-form ref="form" :model="form" label-width="80px" :rules="rules">
<el-form-item label="名称" prop="name">
<el-input v-model="form.name"></el-input>
</el-form-item>
<el-form-item label="上传文件" class="is-required">
<el-upload
class="upload-demo"
drag
action=""
accept=".txt,.jpg"
:on-change="handleChange"
:auto-upload="false"
:file-list="form.file"
:on-remove="handleAddRemove"
multiple
>
<i class="el-icon-upload"></i>
<div class="el-upload__text">将文件拖到此处,或<em>点击上传</em></div>
<div class="el-upload__tip" slot="tip">只能上传txt/jpg文件,且不超过5kb</div>
</el-upload>
<!--文件校验提示信息,在添加el-form-item中class="is-required"-->
<div class="file-error" v-show="errFileMsg">{{errFileMsg}}</div>
</el-form-item>
</el-form>
<span slot="footer" class="dialog-footer">
<el-button @click="changeVisible()">取 消</el-button>
<el-button type="primary" @click="save()">确 定</el-button>
</span>
</el-dialog>
</div>
</template>
<script>
export default {
name: "formDialog7-1",
props: ['dialogVisible'],
data() {
return {
form: {
name: '',
file: []
},
rules: {
name: [{required: true, message: '请输入名称', trigger: 'blur'}],
},
errFileMsg: ''
}
},
methods: {
resetForm() {
this.$refs.form.resetFields();
this.errFileMsg = '';
},
// 取消
changeVisible(value = false) {
this.$emit('update:dialogVisible', value)
},
// 改变文件
handleChange(file, fileList) {
// 个人理解:this.form.file是已有列表,fileList是已有列表加上新加的文件,需手动赋值处理;
// 如果不处理,已有列表会自动显示fileList(检测到this.form.file变化就显示this.form.file,否则显示fileList)
//场景一:用message提示信息最方便
if (this.validateFile(file)) {
//校验通过
this.form.file.push(file);
} else {
//手动更新
this.form.file.splice();
}
//场景二:如果非要在错误信息出显示提醒
// let flag = true;
// this.form.file = [];
// for (let file of fileList) {
// if (this.validateFile(file)) {
// //校验通过
// this.form.file.push(file);
// } else {
// //手动更新
// this.form.file.splice();
// flag = false;
// }
// }
// if (flag) {
// this.errFileMsg = ''
// }
},
//移除文件
handleAddRemove(file, fileList) {
this.form.file = fileList;
},
save() {
const fileLength = this.form.file.length;
this.errFileMsg = fileLength === 0 ? '请上传文件' : '';
if (!this.validate() || fileLength === 0) return;
this.$emit('save', {...this.form})
},
// 文件校验
validateFile(file) {
//场景一:用提示信息最方便,场景二注释
this.errFileMsg = '';
if (!file) {
//场景一:用提示信息最方便
this.$message.error('请上传文件')
// 场景二:如果非要在错误信息出显示提醒
// this.errFileMsg = '请上传文件';
return false;
}
//file格式及大小校验
const validName = file.name.endsWith('.txt') || file.name.endsWith('.jpg');
const validSize = file.size < (1024 * 5);
if (!validName) {
//场景一:用提示信息最方便
this.$message.error('文件类型不正确')
// 场景二:如果非要在错误信息出显示提醒
// this.errFileMsg = '文件类型不正确';
return false;
} else if (!validSize) {
//场景一:用提示信息最方便
this.$message.error('文件大小超出限制')
// 场景二:如果非要在错误信息出显示提醒
// this.errFileMsg = '文件大小超出限制';
return false;
} else {
return true;
}
},
validate() {
let result = false;
this.$refs.form.validate((valid) => {
result = valid;
})
return result;
}
}
}
</script>
<style lang="less" scoped>
.formDialog7-1 {
.file-error {
color: #F56C6C;
font-size: 12px;
line-height: 1;
padding-top: 4px;
position: absolute;
top: 100%;
left: 0;
}
//场景:去掉列表展示的动画效果
/deep/ .el-list-enter-active,
/deep/ .el-list-leave-active {
transition: none;
}
}
</style>
三、upload上传文件及图片,图片预览
功能:1、上传图片校验 2、随表单一块提交 3、图片预览
效果图:
代码:
<template>
<!--功能:1、上传图片校验 2、随表单一块提交 3、图片预览 -->
<div class="add-dialog">
<el-form :inline="true"
ref="addForm"
:model="addForm"
class="demo-form-inline"
label-width="80px"
:rules="rules">
<el-form-item label="姓名:" prop="name">
<el-input style="width:100px;" v-model="addForm.name" placeholder="请输入姓名"></el-input>
</el-form-item>
<el-form-item label="性别:" label-width="80px" prop="sex">
<el-select style="width:150px;" v-model="addForm.sex" placeholder="请选择">
<el-option label="男" value="1"></el-option>
<el-option label="女" value="2"></el-option>
</el-select>
</el-form-item>
<el-form-item label="年龄:" label-width="80px" prop="age">
<el-input style="width:150px;" v-model.number="addForm.age" placeholder="请输入"></el-input>
</el-form-item>
<!--头像-->
<el-form-item label="组头像" prop="file" class="upload-img-form" ref="uploadElement">
<el-upload
class="avatar-uploader"
action=" "
:show-file-list="false"
:on-change="handlePictureCardPreview"
:before-upload="beforeupload"
:limit="1"
>
<img v-if="imageUrl" :src="imageUrl" class="avatar">
<i v-else class="el-icon-plus avatar-uploader-icon"></i>
<!-- <i v-show="!imageUrl" class="el-icon-upload avatar-uploader-icon"></i>-->
<!-- <div v-show="!imageUrl" slot="tip" class="el-upload__text upload__tip">上传照片</div>-->
</el-upload>
</el-form-item>
<!--文件-->
<el-form-item label="上传文件" prop="newFile" class="upload-file-form" ref="uploadFile">
<el-upload
class="upload-demo"
action=""
:show-file-list="false"
:on-change="changeFile"
:before-upload="beforeupload"
:limit="1"
drag
>
<i class="el-icon-upload"></i>
<div class="el-upload__text">将文件拖到此处,或<em>点击上传</em></div>
</el-upload>
</el-form-item>
<el-form-item style="text-align:center;display:block;margin-top:120px">
<el-button type="primary" @click="onSubmit" :disabled="doSubmitFlag">保存</el-button>
</el-form-item>
</el-form>
</div>
</template>
<script>
import model from '../api/model'
export default {
name: 'add-dialog',
computed: {},
data() {
var checkNumber = (rule, value, callback) => {
let regEn = /^[1-9]\d*$/
if (!regEn.test(value)) {
callback(new Error('正整数'))
} else {
callback()
}
}
return {
imageUrl: '',
doSubmitFlag: false,
doUpload: false,
addForm: {
name: '',
sex: '',
age: '',
file: '',
newFile: '',
},
rules: { // 表单验证
name: [
{required: true, message: '必填项', trigger: 'blur'}
],
age: [
{required: true, message: '必填项', trigger: 'blur'},
{validator: checkNumber, trigger: 'blur'}
],
sex: [
{required: true, message: '必填项', trigger: ['blur', 'change']}
],
file: [
{required: true, message: '请上传图片'}
],
newFile: [
{required: true, message: '请上传文件'}
],
},
}
},
mounted() {
},
methods: {
// 图片预览
handlePictureCardPreview(file) {
// 获取url
this.imageUrl = URL.createObjectURL(file.raw)
this.addForm.file = file.raw
this.doUpload = true
this.$refs['addForm'].validateField('file')
},
// 阻止upload的自己上传,进行再操作
beforeupload(file) {
return false
},
//文件
changeFile(file) {
this.addForm.newFile = file.raw
this.$refs['addForm'].validateField('newFile')
},
// 上传
onSubmit: function () {
let formData = new FormData()
this.$refs['addForm'].validate((valid) => {
if (valid) {
for (let key in this.addForm) {
formData.append(key, this.addForm[key])
}
this.doSubmitFlag = true
model.uploadFile(formData).then(res => {
this.doSubmitFlag = false
}).catch(err => {
this.doSubmitFlag = false
})
} else {
this.$message({
type: 'warning',
message: '请填写正确格式'
})
return false
}
})
},
}
}
</script>
<style scoped lang="less">
.add-dialog {
position: relative;
width: 900px;
height: 600px;
margin-left: 200px;
}
/*上传图片样式*/
.avatar-uploader {
border: 1px dashed #d9d9d9;
border-radius: 6px;
}
.avatar-uploader .el-upload {
border: 1px dashed #d9d9d9;
border-radius: 6px;
cursor: pointer;
position: relative;
overflow: hidden;
}
.avatar-uploader .el-upload:hover {
border-color: #409EFF;
}
.avatar-uploader-icon {
font-size: 28px;
color: #8c939d;
width: 178px;
height: 178px;
line-height: 178px;
text-align: center;
}
.avatar {
width: 178px;
height: 178px;
display: block;
}
</style>
四、图片回显
五、新建编辑功能复用、文件回显
效果:
父组件:
<template>
<div class="form-page">
<el-button @click="addItem">新建</el-button>
<el-button @click="editItem">编辑</el-button>
<!--新建-->
<newEditForm ref="addForm" title="新建" :dialogVisible.sync="addVisible" @save="addSave"></newEditForm>
<!--编辑-->
<newEditForm ref="editForm" title="编辑" :dialogVisible.sync="editVisible" :editData="editData"
@save="editSave"></newEditForm>
</div>
</template>
<script>
import newEditForm from '../components/formDialog7-2'
export default {
name: "formDemo7-2",
data() {
return {
addVisible: false,
editVisible: false,
editData: {}
}
},
components: {
newEditForm
},
methods: {
addItem() {
this.addVisible = true;
this.$nextTick(() => {
this.$refs.addForm.resetForm();
})
},
editItem() {
this.editVisible = true;
this.editData = {
name: '张三',
file: [{name: "11.txt"}]
}
this.$nextTick(() => {
this.$refs.editForm.resetForm();
})
},
addSave(data) {
console.log(data);
},
editSave(data) {
console.log(data);
}
}
}
</script>
<style lang="less" scoped>
.formDemo-page {
text-align: left;
}
</style>
子组件:
<template>
<div class="formDialog7-2">
<!--功能(多个文件):1、上传文件校验 2、随表单一块提交 3、文件列表展示 4、列表删除后文件联动
5、支持多个文件上传且分别校验 6、去掉列表展示的动画效果-->
<el-dialog
:title="title"
:visible="dialogVisible"
:close-on-click-modal="false"
:close-on-press-escape="false"
@update:visible="changeVisible()"
width="30%">
<el-form ref="form" :model="form" label-width="80px" :rules="rules">
<el-form-item label="名称" prop="name">
<el-input v-model="form.name"></el-input>
</el-form-item>
<el-form-item label="上传文件" class="is-required" prop="file">
<el-upload
class="upload-demo"
drag
action=""
accept=".txt,.jpg"
:on-change="handleChange"
:auto-upload="false"
:file-list="form.file"
:on-remove="handleAddRemove"
multiple
>
<i class="el-icon-upload"></i>
<div class="el-upload__text">将文件拖到此处,或<em>点击上传</em></div>
<div class="el-upload__tip" slot="tip">只能上传txt/jpg文件,且不超过5kb</div>
</el-upload>
<!--文件校验提示信息,在添加el-form-item中class="is-required"-->
<div class="file-error" v-show="errFileMsg">{{errFileMsg}}</div>
</el-form-item>
</el-form>
<span slot="footer" class="dialog-footer">
<el-button @click="changeVisible()">取 消</el-button>
<el-button type="primary" @click="save()">确 定</el-button>
</span>
</el-dialog>
</div>
</template>
<script>
export default {
name: "formDialog7-2",
props: ['dialogVisible', 'title', 'editData'],
data() {
return {
form: {
name: '',
file: []
},
rules: {
name: [{required: true, message: '请输入名称', trigger: 'blur'}],
},
errFileMsg: ''
}
},
watch: {
editData(value) {
this.form = {...value}
}
},
methods: {
resetForm() {
this.$refs.form.resetFields();
this.errFileMsg = '';
},
// 取消
changeVisible(value = false) {
this.$emit('update:dialogVisible', value)
},
// 改变文件
handleChange(file, fileList) {
// 个人理解:this.form.file是已有列表,fileList是已有列表加上新加的文件,需手动赋值处理;
// 如果不处理,已有列表会自动显示fileList(检测到this.form.file变化就显示this.form.file,否则显示fileList)
//场景一:用message提示信息最方便
console.log(fileList);
if (this.validateFile(file)) {
//校验通过
this.form.file.push(file);
} else {
//手动更新
this.form.file.splice();
}
//场景二:如果非要在错误信息出显示提醒
// let flag = true;
// this.form.file = [];
// for (let file of fileList) {
// if (this.validateFile(file)) {
// //校验通过
// this.form.file.push(file);
// } else {
// //手动更新
// this.form.file.splice();
// flag = false;
// }
// }
// if (flag) {
// this.errFileMsg = ''
// }
},
//移除文件
handleAddRemove(file, fileList) {
this.form.file = fileList;
},
save() {
const fileLength = this.form.file.length;
this.errFileMsg = fileLength === 0 ? '请上传文件' : '';
if (!this.validate() || fileLength === 0) return;
this.$emit('save', this.form)
},
// 文件校验
validateFile(file) {
//场景一:用提示信息最方便,场景二注释
this.errFileMsg = '';
if (!file) {
//场景一:用提示信息最方便
this.$message.error('请上传文件')
// 场景二:如果非要在错误信息出显示提醒
// this.errFileMsg = '请上传文件';
return false;
}
//file格式及大小校验
const validName = file.name.endsWith('.txt') || file.name.endsWith('.jpg');
const validSize = file.size < (1024 * 5);
if (!validName) {
//场景一:用提示信息最方便
this.$message.error('文件类型不正确')
// 场景二:如果非要在错误信息出显示提醒
// this.errFileMsg = '文件类型不正确';
return false;
} else if (!validSize) {
//场景一:用提示信息最方便
this.$message.error('文件大小超出限制')
// 场景二:如果非要在错误信息出显示提醒
// this.errFileMsg = '文件大小超出限制';
return false;
} else {
return true;
}
},
validate() {
let result = false;
this.$refs.form.validate((valid) => {
result = valid;
})
return result;
}
}
}
</script>
<style lang="less" scoped>
.formDialog7-2 {
.file-error {
color: #F56C6C;
font-size: 12px;
line-height: 1;
padding-top: 4px;
position: absolute;
top: 100%;
left: 0;
}
//场景:去掉列表展示的动画效果
/deep/ .el-list-enter-active,
/deep/ .el-list-leave-active {
transition: none;
}
}
</style>