经验首页 前端设计 程序设计 Java相关 移动开发 数据库/运维 软件/图像 大数据/云计算 其他经验
当前位置:技术经验 » JS/JS库/框架 » Vue.js » 查看文章
vue+element-ui中的图片获取与上传
来源:cnblogs  作者:Vine.Y  时间:2019/4/8 12:43:41  对本文有异议

vue+element-ui中的图片获取与上传

工作上接触了一下图片的处理,图片的格式是文件流, 记录如下。

请求图片

请求图片的时候,带上{ responseType: 'blob' }, 否则图片显示的可能是乱码。

  1. axios
  2. .post(url, parmas, { responseType: 'blob' })
  3. .then(res => {
  4. return Promise.resolve(res);
  5. })
  6. .catch(e => {
  7. return Promise.reject(e);
  8. });

显示图片

图片返回的是文件流的形式, 控制台中显示的是乱码。
直接显示二进制图片会出错,所以我们要进行处理。

  1. <!-- template中 -->
  2. <img alt="logo" :src="imageUrl" @error="handleLoadError" />
  1. /*------ script中------*/
  2. let urlCreator = window.URL || window.webkitURL;
  3. let imageUrl = urlCreator.createObjectURL(res);
  4. this.imageUrl = imageUrl;

显示图片中,要对万一图片显示不出来的情况进行处理。使用onerror事件可以对加载图片失败的情况进行处理。

  1. handleLoadError(e) {
  2. const img = e.srcElement;
  3. this.imageUrl = this.errorLoadImg; // 用加载失败的图片替代之
  4. img.onerror = null; // 清除错误:如果错误时加载时显示的图片出错,将会一直循环,所以我们必须清除掉错误,限制运行一次
  5. }

上传图片:使用 element-ui 的 el-upload

自动上传,一次传一张图片

  1. <el-upload
  2. action="uploadUrl"
  3. :show-file-list="false"
  4. :accept="'image/*'"
  5. :headers="{token:$cookieStorage.token}"
  6. :on-success="handleSuccess"
  7. :on-error="handleError"
  8. :before-upload="handleBeforeUpload"
  9. :on-progress="handleProgress"
  10. >
  11. <el-button type="primary" size="medium">上传图片</el-button>
  12. </el-upload>
  13. <!--
  14. action: 图片上传的地址
  15. show-file-list: 是否显示文件上传列表
  16. accept: 可接受的上传类型,image/*为图片
  17. headers: 头部信息
  18. on-success: 上传成功事件
  19. on-error: 上传失败事件
  20. before-upload: 上传前处理事件,返回一个值,值为false将阻止上传
  21. on-progress: 上传中事件
  22. -->
  1. /*----- 以下为常用处理代码 ------*/
  2. handleSuccess(response, file, fileList) {
  3. this.$success("上传成功");
  4. },
  5. handleError() {
  6. this.$error("上传失败,请重新上传图片!");
  7. },
  8. handleBeforeUpload(file) {
  9. const isImage = file.type.includes("image");
  10. if (!isImage) {
  11. this.$message.error("上传文件类型必须是图片!");
  12. }
  13. const isLt2M = file.size / 1024 / 1024 < 2;
  14. if (!isLt2M) {
  15. this.$message.error("上传图片大小不能超过 2MB!");
  16. }
  17. return isImage && isLt2M;
  18. },
  19. handleProgress(event, file, fileList) {
  20. this.loading = true; // 上传时执行loading事件
  21. }

手动上传,一次提交多个 el-upload 的图片

要求:每个 picture area 限制选择一张图片,点击确定后一起提交。

  1. <el-upload
  2. action="myUrl"
  3. :on-change="(file,fileList)=>{handleChange(file,fileList,1)}"
  4. :on-remove="(file,fileList)=>{handleRemove(file,fileList,1)}"
  5. :auto-upload="false"
  6. :file-list="fileList[0]"
  7. ref="file1"
  8. >
  9. <el-button size="small">选择图片</el-button>
  10. </el-upload>
  11. <el-upload
  12. action="myUrl"
  13. :on-change="(file,fileList)=>{handleChange(file,fileList,2)}"
  14. :on-remove="(file,fileList)=>{handleRemove(file,fileList,2)}"
  15. :auto-upload="false"
  16. :file-list="fileList[1]"
  17. ref="file2"
  18. >
  19. <el-button size="small">选择图片</el-button>
  20. </el-upload>
  21. <el-upload
  22. action="myUrl"
  23. :on-change="(file,fileList)=>{handleChange(file,fileList,3)}"
  24. :on-remove="(file,fileList)=>{handleRemove(file,fileList,3)}"
  25. :auto-upload="false"
  26. :file-list="fileList[2]"
  27. ref="file3"
  28. >
  29. <el-button size="small">选择图片</el-button>
  30. </el-upload>
  31. <el-button @click="submitData">确认</el-button>
  32. <!--
  33. action:提交的地址,此处随便写一个,不写会报错
  34. on-change: 图片上传到缓存中将被触发
  35. on-remove: 从缓存中删除文件将被触发
  36. -->
  1. data(){
  2. fileList: [0,0,0], //缓存区文件
  3. uploadFile:[[],[],[]] // 上传用文件
  4. },
  5. handleChange(file, fileList, type) {
  6. // 限制单张上传,超过限制即覆盖
  7. if (fileList.length > 1) {
  8. fileList.splice(0, 1);
  9. }
  10. // 校验
  11. const isLt2M = file.size / 1024 / 1024 < 5;
  12. if (!isLt2M) {
  13. this.$message.error("上传图片大小不能超过 5MB!");
  14. this.removeUploadedFile(type); // 不符合要求删除文件
  15. return false;
  16. }
  17. const isImage = file.raw.type.includes("image");
  18. if (!isImage) {
  19. this.$message.error("上传的格式必须是图片!");
  20. this.removeUploadedFile(type);
  21. return false;
  22. }
  23. // 验证通过之后,将缓存区文件存入上传区文件中
  24. this.formData.files[type] = file.raw;
  25. },
  26. // 从缓存区移除文件
  27. removeUploadedFile(type) {
  28. if (type === 0) {
  29. this.$refs.file1.clearFiles();
  30. }
  31. if (type === 1) {
  32. this.$refs.file2.clearFiles();
  33. }
  34. if (type === 2) {
  35. this.$refs.file3.clearFiles();
  36. }
  37. }
  38. // 删除文件
  39. handleRemove(file, fileList, type) {
  40. // 删除文件时要移除缓存区文件和上传区文件
  41. this.fileList[type] = 0;
  42. this.uploadFile[type] = [];
  43. },
  44. // 上传文件
  45. submitData() {
  46. // 校验是否选择文件
  47. let fileNum = this.flatten(this.uploadFile).length;
  48. if (fileNum === 0) {
  49. this.$error("未选择任何文件!");
  50. return false;
  51. }
  52. // 使用formdata格式
  53. let formData = new FormData();
  54. if (this.formData.files[0]) {
  55. formData.append("file1", this.formData.files[0]);
  56. }
  57. if (this.formData.files[1]) {
  58. formData.append("file2", this.formData.files[1]);
  59. }
  60. if (this.formData.files[2]) {
  61. formData.append("file2", this.formData.files[2]);
  62. }
  63. // 请求:在headers上务必加上content-Type,指定表单形式发送
  64. axios
  65. .post("uploadUrl", formData, {headers: { "Content-Type": "multipart/form-data" }})
  66. .then(res => {
  67. this.$success("上传图片成功!");
  68. this.fileList = [0,0,0];
  69. this.uploadFile =[[],[],[]];
  70. })
  71. .catch(e => {
  72. console.log(e);
  73. });
  74. }
  75. // 扁平化数组
  76. flatten(arr) {
  77. let res = [];
  78. for (let i = 0; i < arr.length; i++) {
  79. if (Array.isArray(arr[i])) {
  80. res = res.concat(this.flatten(arr[i]));
  81. } else {
  82. res.push(arr[i]);
  83. }
  84. }
  85. return res;
  86. }

multipartform-data相关知识

图片加载技术:预加载和懒加载

  • 预加载:重点在"预",在用户需要看到该图片之前,就已经加载和请求到该图片。
  • 懒加载: 重点在"懒",尽可能少的加载图片,只加载必需的图片(用户屏幕可视范围内),目的是尽可能的减少请求数,减缓服务器的压力。
    在vue中懒加载的组件有很多,比如vue-lazy-laodvue-clazy-load

浏览器阻塞

同一时间对服务器的请求过多,将会造成浏览器阻塞。
浏览器默认对同一域下的资源,只保持一定的连接数,阻塞过多的连接,以提高访问速度和解决阻塞问题。

对于请求图片来说,有以下解决方法

  1. 使用雪碧图:把所有图片合成一张大图。
  2. 延迟加载:只去请求可视区的图片。
    最后使用了延迟加载,对非可视区领域的图片延迟加载,优先加载可视区图片,减少图片的请求数。
  1. <img :src="imageUrl" ref="img">
  1. // 方式一:延迟加载非可视区域
  2. delayTime() {
  3. let windowHeight = window.innerHeight;
  4. let imgTop = this.$refs.img.getBoundingClientRect().top;
  5. const isDelay = imgTop > windowHeight;
  6. if (isDelay) {
  7. return Math.random() * 2000 + 3000;
  8. } else {
  9. return Math.random() * 2000 + 500;
  10. }
  11. }
  12. // 方法二:按顺序依次延迟加载
  13. delayTime() {
  14. if (this.params.index) {
  15. return Math.random() * 2000 + this.params.index * this.params.type * 500;
  16. } else {
  17. return 0;
  18. }
  19. }
  20. setTimeout(() => {
  21. // 图片请求代码
  22. }, this.delayTime);

使用延时加载前的请求
使用延时加载前的请求

使用延时加载后的请求
使用延时记载后的请求

参考

[1] XMLHttpRequest Standard.The responseType attribute
[2] XMLHttpRequest.responseType | MDN
[3] 理解DOMString、Document、FormData、Blob、File、ArrayBuffer数据类型 ? 张鑫旭-鑫空间-鑫生活
[4] FormData 对象的使用 | MDN
[5] 前端|加载的图片太多或者太大怎么办(上) - u012496505的博客 - CSDN博客
[6] Lazy Loading Images and Video ?|? Web Fundamentals ?|? Google Developers
[7] An Introduction to Progressive Image Rendering
[8] 原生 JS 实现最简单的图片懒加载 - WEB前端 - 伯乐在线

2019/1/14 9:15:33

原文链接:http://www.cnblogs.com/yejingping/p/10662204.html

 友情链接:直通硅谷  点职佳  北美留学生论坛

本站QQ群:前端 618073944 | Java 606181507 | Python 626812652 | C/C++ 612253063 | 微信 634508462 | 苹果 692586424 | C#/.net 182808419 | PHP 305140648 | 运维 608723728

W3xue 的所有内容仅供测试,对任何法律问题及风险不承担任何责任。通过使用本站内容随之而来的风险与本站无关。
关于我们  |  意见建议  |  捐助我们  |  报错有奖  |  广告合作、友情链接(目前9元/月)请联系QQ:27243702 沸活量
皖ICP备17017327号-2 皖公网安备34020702000426号