Vue上传图片预览组件
父组件:
<template>
<div>
<h4>基于Vue.2X的html5上传图片组件</h4>
<div style="width: 502px;">
<uploader :src="'/api/imgsupload'"></uploader>
</div>
</div>
</template>
<script>
import uploader from './uploader.vue'
export default {
data() {
return {}
},
components: {
uploader
}
}
</script>
子组件:
<template>
<div class="vue-uploader">
<div class="file-list">
<section v-for="(file, index) of files" class="file-item draggable-item">
<img :src="file.src" alt="" ondragstart="return false;">
<p class="file-name">{{file.name}}</p>
<span class="file-remove" @click="remove(index)">+</span>
</section>
<section v-if="status == 'ready'" class="file-item">
<div @click="add" class="add">
<span>+</span>
</div>
</section>
</div> <section v-if="files.length != 0" class="upload-func">
<div class="progress-bar">
<section v-if="uploading" :width="(percent * 100) + '%'">{{(percent * ) + '%'}}</section>
</div>
<div class="operation-box">
<button v-if="status == 'ready'" @click="submit">上传</button>
<button v-if="status == 'finished'" @click="finished">完成</button>
</div>
</section>
<input type="file" accept="image/*" @change="fileChanged" ref="file" multiple="multiple">
</div>
</template>
<script>
export default {
props: {
src: {
type: String,
required: true
}
},
data() {
return {
status: 'ready',
files: [],
uploading: false,
percent:
}
},
methods: {
add() {
this.$refs.file.click()//调用file的click事件
},
submit() {
if (this.files.length === ) {
console.warn('no file!');
return
}
//当点击上传按钮时,将会遍历所有选中的文件,并添加到自定义的FormData中
const formData = new FormData()
this.files.forEach((item) => {
formData.append(item.name, item.file)
})
const xhr = new XMLHttpRequest()
xhr.upload.addEventListener('progress', this.uploadProgress, false)
xhr.open('POST', this.src, true)
this.uploading = true
xhr.send(formData)
xhr.onload = () => {
this.uploading = false
if (xhr.status === || xhr.status === ) {
this.status = 'finished'
console.log('upload success!')
} else {
console.log(`error:error code ${xhr.status}`)
}
}
},
finished() {
this.files = []
this.status = 'ready'
},
remove(index) {
this.files.splice(index, )
},
fileChanged() {
const list = this.$refs.file.files
for (let i = ; i < list.length; i++) {
if (!this.isContain(list[i])) {
const item = {
name: list[i].name,
size: list[i].size,
file: list[i]
}
this.html5Reader(list[i], item)
this.files.push(item)
}
}
this.$refs.file.value = ''
},
// 将图片文件转成BASE64格式
html5Reader(file, item){
const reader = new FileReader()
reader.onload = (e) => {
this.$set(item, 'src', e.target.result)
}
reader.readAsDataURL(file)
},
isContain(file) {
return this.files.find((item) => item.name === file.name && item.size === file.size)
},
uploadProgress(evt) {
const component = this
if (evt.lengthComputable) {
const percentComplete = Math.round((evt.loaded * ) / evt.total)
component.percent = percentComplete /
} else {
console.warn('upload progress unable to compute')
}
}
}
}
</script>
<style>
.vue-uploader {
border: 1px solid #e5e5e5;
}
.vue-uploader .file-list {
padding: 10px 0px;
}
.vue-uploader .file-list:after {
content: '';
display: block;
clear: both;
visibility: hidden;
line-height: ;
height: ;
font-size: ;
}
.vue-uploader .file-list .file-item {
float: left;
position: relative;
width: 100px;
text-align: center;
}
.vue-uploader .file-list .file-item img{
width: 80px;
height: 80px;
border: 1px solid #ececec;
}
.vue-uploader .file-list .file-item .file-remove {
position: absolute;
right: 12px;
display: none;
top: 4px;
width: 14px;
height: 14px;
color: white;
cursor: pointer;
line-height: 12px;
border-radius: %;
transform: rotate(45deg);
background: rgba(, , , 0.5);
}
.vue-uploader .file-list .file-item:hover .file-remove {
display: inline;
}
.vue-uploader .file-list .file-item .file-name {
margin: ;
height: 40px;
word-break: break-all;
font-size: 14px;
overflow: hidden;
text-overflow: ellipsis;
display: -webkit-box;
-webkit-line-clamp: ;
-webkit-box-orient: vertical;
}
.vue-uploader .add {
width: 80px;
height: 80px;
margin-left: 10px;
float: left;
text-align: center;
line-height: 80px;
border: 1px dashed #ececec;
font-size: 30px;
cursor: pointer;
}
.vue-uploader .upload-func {
display: flex;
padding: 10px;
margin: 0px;
background: #f8f8f8;
border-top: 1px solid #ececec;
}
.vue-uploader .upload-func .progress-bar {
flex-grow: ;
}
.vue-uploader .upload-func .progress-bar section {
margin-top: 5px;
background: #00b4aa;
border-radius: 3px;
text-align: center;
color: #fff;
font-size: 12px;
transition: all .5s ease;
}
.vue-uploader .upload-func .operation-box {
flex-grow: ;
padding-left: 10px;
}
.vue-uploader .upload-func .operation-box button {
padding: 4px 12px;
color: #fff;
background: #007ACC;
border: none;
border-radius: 2px;
cursor: pointer;
}
.vue-uploader > input[type="file"] {
display: none;
}
</style>
效果:
Vue上传图片预览组件的更多相关文章
- [js开源组件开发]-手机端照片预览组件
手机端照片预览组件 可怜的我用着华为3C手机,用别人现成的组件都好卡,为了适应我这种屌丝,于是自己简化写了一版的照片预览效果,暂时无缩放功能,以后可能有空再加吧,你也可以自己加下,这是个github上 ...
- HTML5上传图片预览
<!DOCTYPE html> <html> <head> <title>HTML5上传图片预览</title> <meta http ...
- jquery实现上传图片预览(需要浏览器支持html5)
jquery实现上传图片预览(需要浏览器支持html5) <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN&q ...
- HTML5上传图片预览功能
HTML5上传图片预览功能 HTML代码如下: <!-- date: 2018-04-27 14:41:35 author: 王召波 descride: HTML5上传图片预览功能 --> ...
- 图片预览组件PhotoView
图片预览组件PhotoView PhotoView是一款图片预览组件,广泛应用于大图的查看.该组件支持图片手势缩放.旋转等功能.它可以很好的和ViewPager.Picasso等组件结合,实现各种复杂 ...
- JS 上传图片 + 预览功能(一)
JS 上传图片 + 预览功能 <body> <input type="file" id="fileimg1" style="disp ...
- js兼容火狐显示上传图片预览效果
js兼容火狐显示上传图片预览效果[谷歌也适用] <!doctype html> <html> <head> <meta content="text/ ...
- 通过HTML5 FileReader实现上传图片预览功能
原文:http://www.htmleaf.com/ziliaoku/qianduanjiaocheng/201706224590.html 在上传图片到服务器之前,我们希望可以预览一下要上传的图片. ...
- 去除ckeditor上传图片预览中的英文字母
去除ckeditor上传图片预览中的英文字母 CKEDITOR.replace('text', { filebrowserImageUploadUrl : 'upload_img.do', langu ...
随机推荐
- SHOI2019旅游记
题外话 为什么不更ZJOI day1的游记呢.... 因为考挂自闭了不想更.等day2考完再说咕咕咕 还是更个SHOI旅游记吧!反正不是自家省选,玩得真开心~~~ day0 SH好热好热啊,感觉到夏天 ...
- 2010-2011 ACM-ICPC, NEERC, Moscow Subregional Contest Problem H. Hometask 水题
Problem H. Hometask 题目连接: http://codeforces.com/gym/100714 Description Kolya is still trying to pass ...
- js 弹窗广告24小时显示一次
弹窗24小时显示一次 https://www.w3cschool.cn/javascript/js-cookies.html 我们需要借助cookie来实现这个功能 function setcooki ...
- 使用 IntraWeb (19) - 基本控件之 TIWTreeView
这是个饱受非议的控件; 我通过尝试, 理解了非议, 也能理解作者. 总之向作者的思路靠拢吧, 还是不错的. TIWTreeView 所在单元及继承链: IWCompTreeview.TIWTreeVi ...
- Groovy中Closure的this到底指向谁?
Groovy in Action(中文版)第136页明确说Closure的this指向Closure自己.并且从代码注释处作者也是这样理解的: class Mother{ int field = ...
- In-Place upgrade to Team Foundation Server (TFS) 2015 from TFS 2013Team Foundation Server TFS TFS 2015 TFS upgrade TFS with Sharepoint
This upgrade document gives detailed step by step procedure for the In-Place upgrade from TFS 2013 t ...
- 使用jQuery实现图片懒加载原理
原文:https://www.liaoxuefeng.com/article/00151045553343934ba3bb4ed684623b1bf00488231d88d000 在网页中,常常需要用 ...
- frame与bounds的区别比较
翻译文档上的 bounds是指这个view在它自己坐标系的坐标和大小 而frame指的是这个view在它superview的坐标系的坐标和大小 区别主要在坐标系这一块. 很明显一个是自己为原点的坐标 ...
- ios 判断app程序第一次启动方法
if(![[NSUserDefaults standardUserDefaults] boolForKey:@"firstStart"]){ [[NSUserDefaults st ...
- Android Timer schedule
timer.schedule(new MyTask(),long time1,long timer2); 今天算是彻底的搞懂了这个以前让我为之头疼的方法. 以下我就重点介绍一下: 第一个參数.是 Ti ...