search
HomeWeb Front-endJS TutorialDetailed explanation of the steps to encapsulate the lightweight upload file component in Vue

This time I will bring you a detailed explanation of the steps to encapsulate the lightweight upload file component in Vue. What are the precautions for encapsulating the lightweight upload file component in Vue. Here are practical cases, let’s take a look.

1. Some problems encountered before

There are many requirements for uploading files in the project, which is implemented using the existing UI framework During the process, there will always be some inexplicable bugs for some unknown reason. For example, when using a certain upload component, it is clearly marked (:multiple="false"), but in fact it is still possible to select multiple files, and multiple files are still sent when uploading; for example, as long as (:file-list="fileList" is added) ") attribute, when I hope to manually control the upload list, the upload event this.refs.[upload (component ref)].submit() will not work and cannot be transmitted. In short, I am too lazy to see how to implement it. I am using the function, and the interface itself still needs to be rewritten. If I insist on using it, it will add a lot of unnecessary logic and style code to the project...

Used before The view frameworks used by Vue for projects include element-ui, zp-ui as a supplement within the team, and iview. The framework is easy to use, but you often can’t use it for your own projects. Especially the interface created by our design girl is very different from the existing framework. Changing the source code is inefficient and can easily lead to unknown bugs, so I take the time to do it myself. Encapsulates this upload component.

2. Code and introduction

Parent component

<template>
 <p>
 <label>
  <span>上传</span>
 </label>
  <my-upload>
  </my-upload>
  <button>Upload</button>
 </p>
</template>
<script>
import myUpload from &#39;./components/my-upload&#39;
export default {
 name: &#39;test&#39;,
 data(){
  return {
  fileList: [],//上传文件列表,无论单选还是支持多选,文件都以列表格式保存
  param: {param1: &#39;&#39;, param2: &#39;&#39; },//携带参数列表
  }
 },
 methods: {
  onChange(fileList){//监听文件变化,增减文件时都会被子组件调用
  this.fileList = [...fileList];
  },
  uploadSuccess(index, response){//某个文件上传成功都会执行该方法,index代表列表中第index个文件
  console.log(index, response);
  },
  upload(){//触发子组件的上传方法
  this.$refs.myUpload.submit();
  },
  removeFile(index){//移除某文件
  this.$refs.myUpload.remove(index);
  },
  uploadProgress(index, progress){//上传进度,上传时会不断被触发,需要进度指示时会很有用
  const{ percent } = progress;
  console.log(index, percent);
  },
  uploadFailed(index, err){//某文件上传失败会执行,index代表列表中第index个文件
  console.log(index, err);
  },
  onFinished(result){//所有文件上传完毕后(无论成败)执行,result: { success: 成功数目, failed: 失败数目 }
  console.log(result);
  }
 },
 components: {
  myUpload
 }
}
</script>

The parent component handles business-related logic, I specially added it The index parameter allows the interface to directly manipulate the value when displaying the upload result. It is not required for all methods and can be used according to needs.

Subcomponent

<template>
<p>
 <input>
</p>
</template>

Upload the file, the html part is just a pair of tags, I don’t like the complexity

<script>
export default {
 name: &#39;my-upload&#39;,
 props: {
 name: String,
 action: {
  type: String,
  required: true
 },
 fileList: {
  type: Array,
  default: []
 },
 data: Object,
 multiple: Boolean,
 limit: Number,
 onChange: Function,
 onBefore: Function,
 onProgress: Function,
 onSuccess: Function,
 onFailed: Function,
 onFinished: Function
 },
 methods: {}//下文主要是methods的介绍,此处先省略
}
</script>

This defines the attributes that need to be passed from the parent component to the child component Value, please note that the method is also passed as an attribute here, which is acceptable.

The components I wrote are not as complete and comprehensive as those released by popular frameworks. In addition, in view of the problem mentioned at the beginning that the bound file-list cannot be uploaded (more likely because my posture is wrong), I I also want to try my best to solve this problem I encountered, so I hope to have absolute control over the file list. In addition to action, file-list is also used as an attribute that must be passed by the parent component. (The attribute name of the parent component is connected with "-", corresponding to the camel case naming in the child component prop)

3. Main upload function

methods: {
  addFile, remove, submit, checkIfCanUpload
}
## There are a total of 4 methods in #methods, including adding files, removing files, submitting, and testing (testing before uploading). They are described one by one below:

1. Add files

addFile({target: {files}}){//input标签触发onchange事件时,将文件加入待上传列表
 for(let i = 0, l = files.length; i  0 && l > limit){//有数目限制时,取后面limit个文件
  limit = Math.ceil(limit);
//  limit = limit > 10 ? 10 : limit;
  fileList = fileList.slice(l - limit);
 }
 }else{//单选时,只取最后一个文件。注意这里没写成fileList = files;是因为files本身就有多个元素(比如选择文件时一下子框了一堆)时,也只要一个
 fileList = [files[0]];
 }
 this.onChange(fileList);//调用父组件方法,将列表缓存到上一级data中的fileList属性
 },
2. Move Deleting files

is simple. Sometimes when the parent component forks a file, just pass an index.

remove(index){
 let fileList = [...this.fileList];
 if(fileList.length){
 fileList.splice(index, 1);
 this.onChange(fileList);
 }
},
3. Submit upload

There are two methods used here, fetch and native method. Since fetch does not support getting the upload progress, if you don’t need

progress baror When you simulate the progress yourself or the XMLHttpRequest object does not exist, it will be simpler to use fetch to request the upload logic

submit(){
 if(this.checkIfCanUpload()){
 if(this.onProgress && typeof XMLHttpRequest !== 'undefined')
  this.xhrSubmit();
 else
  this.fetchSubmit();
 }
},
4. Based on the two sets of upload logic, two methods xhrSubmit and fetchSubmit

## are encapsulated here #fetchSubmit

fetchSubmit(){
 let keys = Object.keys(this.data), values = Object.values(this.data), action = this.action;
 const promises = this.fileList.map(each => {
 each.status = "uploading";
 let data = new FormData();
 data.append(this.name || 'file', each);
 keys.forEach((one, index) => data.append(one, values[index]));
 return fetch(action, {
  method: 'POST',
  headers: {
   "Content-Type" : "application/x-www-form-urlencoded"
  },
  body: data
 }).then(res => res.text()).then(res => JSON.parse(res));//这里res.text()是根据返回值类型使用的,应该视情况而定
 });
 Promise.all(promises).then(resArray => {//多线程同时开始,如果并发数有限制,可以使用同步的方式一个一个传,这里不再赘述。
 let success = 0, failed = 0;
 resArray.forEach((res, index) => {
  if(res.code == 1){
  success++;         //统计上传成功的个数,由索引可以知道哪些成功了
  this.onSuccess(index, res);
  }else if(res.code == 520){   //约定失败的返回值是520
  failed++;         //统计上传失败的个数,由索引可以知道哪些失败了
  this.onFailed(index, res);
  }
 });
 return { success, failed };   //上传结束,将结果传递到下文
 }).then(this.onFinished);      //把上传总结果返回
},

xhrSubmit

xhrSubmit(){
  const _this = this;
 let options = this.fileList.map((rawFile, index) => ({
 file: rawFile,
 data: _this.data,
    filename: _this.name || "file",
    action: _this.action,
    onProgress(e){
     _this.onProgress(index, e);//闭包,将index存住
    },
    onSuccess(res){
     _this.onSuccess(index, res);
    },
    onError(err){
     _this.onFailed(index, err);
    }
  }));
 let l = this.fileList.length;
 let send = async options => {
 for(let i = 0; i <p style="text-align: left;">This is based on the upload source code of element-ui</p><pre class="brush:php;toolbar:false">sendRequest(option){
 const _this = this;
  upload(option);
 function getError(action, option, xhr) {
  var msg = void 0;
  if (xhr.response) {
   msg = xhr.status + ' ' + (xhr.response.error || xhr.response);
  } else if (xhr.responseText) {
   msg = xhr.status + ' ' + xhr.responseText;
  } else {
   msg = 'fail to post ' + action + ' ' + xhr.status;
  }
  var err = new Error(msg);
  err.status = xhr.status;
  err.method = 'post';
  err.url = action;
  return err;
 }
 function getBody(xhr) {
  var text = xhr.responseText || xhr.response;
  if (!text) {
   return text;
  }
  try {
   return JSON.parse(text);
  } catch (e) {
   return text;
  }
 }
 function upload(option) {
  if (typeof XMLHttpRequest === 'undefined') {
   return;
  }
  var xhr = new XMLHttpRequest();
  var action = option.action;
  if (xhr.upload) {
   xhr.upload.onprogress = function progress(e) {
    if (e.total > 0) {
     e.percent = e.loaded / e.total * 100;
    }
    option.onProgress(e);
   };
  }
  var formData = new FormData();
  if (option.data) {
   Object.keys(option.data).map(function (key) {
    formData.append(key, option.data[key]);
   });
  }
  formData.append(option.filename, option.file);
  xhr.onerror = function error(e) {
   option.onError(e);
  };
  xhr.onload = function onload() {
   if (xhr.status = 300) {
    return option.onError(getError(action, option, xhr));
   }
   option.onSuccess(getBody(xhr));
  };
  xhr.open('post', action, true);
  if (option.withCredentials && 'withCredentials' in xhr) {
   xhr.withCredentials = true;
  }
  var headers = option.headers || {};
  for (var item in headers) {
   if (headers.hasOwnProperty(item) && headers[item] !== null) {
    xhr.setRequestHeader(item, headers[item]);
   }
  }
  xhr.send(formData);
  return xhr;
 }
}

Finally add the verification before the request

checkIfCanUpload(){
 return this.fileList.length ? (this.onBefore && this.onBefore() || !this.onBefore) : false;
},

If If the parent component defines the onBefore method and returns false, or the file list is empty, the request will not be sent.

The code part is finished. When using it, as long as the on-progress attribute is present and the XMLHttpRequest object is accessible, the request will be sent in the native way. Otherwise, the request will be sent using fetch (the progress will not be displayed).

I believe you have mastered the method after reading the case in this article. For more exciting information, please pay attention to other related articles on the php Chinese website!

Recommended reading:

Use case description of the filter() method in jquery


Detailed explanation of the steps to use WebUploader in the fuzzy box

The above is the detailed content of Detailed explanation of the steps to encapsulate the lightweight upload file component in Vue. For more information, please follow other related articles on the PHP Chinese website!

Statement
The content of this article is voluntarily contributed by netizens, and the copyright belongs to the original author. This site does not assume corresponding legal responsibility. If you find any content suspected of plagiarism or infringement, please contact admin@php.cn
The Future of Python and JavaScript: Trends and PredictionsThe Future of Python and JavaScript: Trends and PredictionsApr 27, 2025 am 12:21 AM

The future trends of Python and JavaScript include: 1. Python will consolidate its position in the fields of scientific computing and AI, 2. JavaScript will promote the development of web technology, 3. Cross-platform development will become a hot topic, and 4. Performance optimization will be the focus. Both will continue to expand application scenarios in their respective fields and make more breakthroughs in performance.

Python vs. JavaScript: Development Environments and ToolsPython vs. JavaScript: Development Environments and ToolsApr 26, 2025 am 12:09 AM

Both Python and JavaScript's choices in development environments are important. 1) Python's development environment includes PyCharm, JupyterNotebook and Anaconda, which are suitable for data science and rapid prototyping. 2) The development environment of JavaScript includes Node.js, VSCode and Webpack, which are suitable for front-end and back-end development. Choosing the right tools according to project needs can improve development efficiency and project success rate.

Is JavaScript Written in C? Examining the EvidenceIs JavaScript Written in C? Examining the EvidenceApr 25, 2025 am 12:15 AM

Yes, the engine core of JavaScript is written in C. 1) The C language provides efficient performance and underlying control, which is suitable for the development of JavaScript engine. 2) Taking the V8 engine as an example, its core is written in C, combining the efficiency and object-oriented characteristics of C. 3) The working principle of the JavaScript engine includes parsing, compiling and execution, and the C language plays a key role in these processes.

JavaScript's Role: Making the Web Interactive and DynamicJavaScript's Role: Making the Web Interactive and DynamicApr 24, 2025 am 12:12 AM

JavaScript is at the heart of modern websites because it enhances the interactivity and dynamicity of web pages. 1) It allows to change content without refreshing the page, 2) manipulate web pages through DOMAPI, 3) support complex interactive effects such as animation and drag-and-drop, 4) optimize performance and best practices to improve user experience.

C   and JavaScript: The Connection ExplainedC and JavaScript: The Connection ExplainedApr 23, 2025 am 12:07 AM

C and JavaScript achieve interoperability through WebAssembly. 1) C code is compiled into WebAssembly module and introduced into JavaScript environment to enhance computing power. 2) In game development, C handles physics engines and graphics rendering, and JavaScript is responsible for game logic and user interface.

From Websites to Apps: The Diverse Applications of JavaScriptFrom Websites to Apps: The Diverse Applications of JavaScriptApr 22, 2025 am 12:02 AM

JavaScript is widely used in websites, mobile applications, desktop applications and server-side programming. 1) In website development, JavaScript operates DOM together with HTML and CSS to achieve dynamic effects and supports frameworks such as jQuery and React. 2) Through ReactNative and Ionic, JavaScript is used to develop cross-platform mobile applications. 3) The Electron framework enables JavaScript to build desktop applications. 4) Node.js allows JavaScript to run on the server side and supports high concurrent requests.

Python vs. JavaScript: Use Cases and Applications ComparedPython vs. JavaScript: Use Cases and Applications ComparedApr 21, 2025 am 12:01 AM

Python is more suitable for data science and automation, while JavaScript is more suitable for front-end and full-stack development. 1. Python performs well in data science and machine learning, using libraries such as NumPy and Pandas for data processing and modeling. 2. Python is concise and efficient in automation and scripting. 3. JavaScript is indispensable in front-end development and is used to build dynamic web pages and single-page applications. 4. JavaScript plays a role in back-end development through Node.js and supports full-stack development.

The Role of C/C   in JavaScript Interpreters and CompilersThe Role of C/C in JavaScript Interpreters and CompilersApr 20, 2025 am 12:01 AM

C and C play a vital role in the JavaScript engine, mainly used to implement interpreters and JIT compilers. 1) C is used to parse JavaScript source code and generate an abstract syntax tree. 2) C is responsible for generating and executing bytecode. 3) C implements the JIT compiler, optimizes and compiles hot-spot code at runtime, and significantly improves the execution efficiency of JavaScript.

See all articles

Hot AI Tools

Undresser.AI Undress

Undresser.AI Undress

AI-powered app for creating realistic nude photos

AI Clothes Remover

AI Clothes Remover

Online AI tool for removing clothes from photos.

Undress AI Tool

Undress AI Tool

Undress images for free

Clothoff.io

Clothoff.io

AI clothes remover

Video Face Swap

Video Face Swap

Swap faces in any video effortlessly with our completely free AI face swap tool!

Hot Tools

Atom editor mac version download

Atom editor mac version download

The most popular open source editor

SAP NetWeaver Server Adapter for Eclipse

SAP NetWeaver Server Adapter for Eclipse

Integrate Eclipse with SAP NetWeaver application server.

Dreamweaver Mac version

Dreamweaver Mac version

Visual web development tools

VSCode Windows 64-bit Download

VSCode Windows 64-bit Download

A free and powerful IDE editor launched by Microsoft

WebStorm Mac version

WebStorm Mac version

Useful JavaScript development tools