VUE——Axios【带进度条上传文件】

使用axios可以实现文件上传功能,并且可以获取上传进度,实现带进度条的上传文件功能

<template>
  <div>
          <div>
             <div> <input type="file" /></div>
           	  <div class="prog_wrap">
             	 <div class="text">0%</div>  // 进度百分比 
             	 <div class="proing" ></div>    // 进度条
             </div>
          </div>
         
  </div>
</template>


<script>
export default{
    name:'up_loadfile',
    data(){
        return  { dataList:[]  }
    },
   
</script>

<style>
.prog_wrap{ width: 300px; height: 40px; border: 1px solid black; position: relative;}
.text{ position: absolute;top: 50%;left: 50%; transform:translate(-50%,-50%);}
.proing{ width: 0%; height: 100%; background-color: aquamarine;}
</style>

在这里插入图片描述

上传的逻辑

  console.log(e.target.files[0])

在控制台打印 “上传第一个图片的信息 ”
console.log(e.target.files[0])
在这里插入图片描述

 uploadfile(e){

        console.log(e.target.files[0])
        let file=e.target.files[0];

        let formData=new FormData();
         formData.append("headfile",file);//将文件file用接口参数headfile来承载
}

头像上传接口:方式:post 。参数:headfile=图片路径
在这里插入图片描述

Axios.post( ).then()上传后返回的响应信息

msbox是图片名称在这里插入图片描述

<template>
  <div>
    <div>
      <input type="file" @change="uploadfile" />
-------------------------------------  
进度条盒子
  
      <div class="prog_wrap">
        <div class="text">{{progVal}}%</div>  // 百分比
        
        <div class="proing" :style="{width:progVal+'%'}"></div>  //进度条 
      </div>
      
进度条盒子      
------------------------------------- 

    </div>
    <div>图片预览效果:<img :src="showImage" alt="" /></div>
  </div>
</template>

<script>

import Axios  from 'axios';//使用Axios  


export default{
    name:'up_loadfile',
    data(){
        return  {
            progVal:0,
            showImage:""
        }
    },
   methods:{
    uploadfile(e){
        console.log(e.target.files[0])
        let file=e.target.files[0];

        let formData=new FormData();
         formData.append("headfile",file);//将文件添加到 FormData对象实例中
//--------------------------------------------------
//进度条
        let config = {
            onUploadProgress: (progressEvent)=>{
              let percentCompleted = Math.round( (progressEvent.loaded * 100) / progressEvent.total );
               console.log(percentCompleted); //如果图片上传成功则控制台显示100%,percentCompleted是进度值
               this.progVal=percentCompleted
            }

          };
//--------------------------------------------------
 //  Axios:                     
   //第一参数接口文档,第二个参数是数据,第三个参数是进度条
    Axios.post(this.$config.baseApi+"/user/myinfo/formdatahead?token="+this.$config.token,formData,config).then(res=>{console.log(res)
                if(res.data.code==200){ //判断是否post成功
                        this.showImage="http://vueshop.glbuys.com/userfiles/head/"+res.data.data.msbox;
                }
        })
//----------------------------------------------------------
         


    }
   }
}
</script>

<style>
.prog_wrap{ width: 300px; height: 40px; border: 1px solid black; position: relative;}
.text{ position: absolute;top: 50%;left: 50%; transform:translate(-50%,-50%);}
.proing{ width: 0%; height: 100%; background-color: aquamarine;}
</style>

在这里插入图片描述
问题1:uploadfile(e)中e是事件对象作为参数,那请问,是只有change类型的事件才有e事件对象作为参数,还是其他类型的事件,也具有e事件对象作为参数
【Vue.js中事件处理函数的参数e(事件对象)的适用范围】

在Vue中,当我们在模板里使用事件监听,比如@click、@input、@change等,绑定的事件处理函数会被自动传入一个事件对象e。这个e是原生的JavaScript事件对象,它包含了事件相关的信息,比如触发事件的元素、事件类型、时间戳等等。在原生JavaScript中,事件处理函数默认都会接收到这个事件对象作为第一个参数,只要定义了参数就可以访问到。

所有的事件处理函数都会接收到事件对象e,只要在方法中声明这个参数。比如,@click、@input、@keyup等等,这些事件的处理函数都可以访问到e对象。而不仅仅是@change事件。

uploadfile方法接收了e参数,并在其中获取了e.target.files[0],这是处理文件上传时常用的方式。这里的e是change事件的事件对象,当文件选择后触发change事件,e.target指向input元素,从而获取文件信息。

Vue官方文档,事件处理部分提到,当使用内联语句的方式,比如@click=“handleClick”,如果没有参数,方法会默认接收事件对象作为第一个参数。如果提供了参数,
如@click=“handleClick(‘arg’, event)”,则需要显式传递event来获取事件对象。

所以,不管事件类型是什么,只要事件被触发,事件处理函数如果没有参数,就会接收到这个e对象。而像@change、@click等事件都是如此。因此,e对象是每个事件处理函数都有的,前提是没有被其他参数覆盖。

关键点解析:

1. 所有事件都有事件对象 e
只要触发的是原生 DOM 事件(如 click、change、input 等),对应的处理函数默认都会自动接收事件对象 e 。这个对象包含事件相关的信息(如触发元素、事件类型、坐标等)。

2. 显式声明参数才能访问 e
在 Vue 模板中,如果事件处理函数没有显式传递参数,e 会自动作为第一个参数传入。例如:

------------------
HYML

<button @click="handleClick">点击</button>
---------------------
JS

methods: {
  handleClick(e) { // 自动接收 e 对象
    console.log(e.target); // 输出触发事件的元素
  }
}

3.如果自定义参数,需用 $event 手动传递 e
当处理函数需要其他参数时,需手动传递 $event 以保留事件对象:

-------------------------------
html
<button @click="handleClick('参数', $event)">点击</button>
-----------------------------------
js

methods: {
  handleClick(arg, e) { // 通过 $event 获取 e
    console.log(arg, e.target);
  }
}

<input type=“file” @change=“uploadfile” />中,@change=“uploadfile” 没有传递参数,因此 uploadfile 方法默认接收 e 作为参数

问题2:e的内容

在 JavaScript 和 Vue 中,事件对象 e(或 event)是浏览器在事件触发时自动创建的一个对象,它记录了事件发生时的所有相关信息,并提供了控制事件行为的方法。它的存在是为了让开发者能更精细地处理事件

e 的具体内容取决于事件类型(如 click、change、keydown),以下是通用属性和方法:
在这里插入图片描述

问题3:FormData对象

1. FormData 是什么:
它是浏览器提供的一个 API,专门用于构造表单数据,适合通过 JavaScript 发送文件或表单数据到服务器。
可以自动处理文件、二进制数据、文本字段的编码,无需手动拼接数据。常用于通过 AJAX(如 Axios、Fetch)上传文件。

let formData = new FormData();
作用:创建一个空的 FormData 对象。

2. formData.append(“headfile”, file);
append的作用:向 FormData 对象中添加一个键值对,键名为 “headfile”,值为用户选择的文件(file)。

参数说明:
“headfile”:服务器接口要求的字段名(需与后端约定,例如后端通过 headfile 字段接收文件)。
file:用户通过 < input type=“file”> 选择的文件对象(即 e.target.files[0])。

总结:
FormData 是处理文件上传的标准工具。
append 方法将文件添加到表单数据中,键名需与后端匹配。
最终通过 HTTP 请求(如 Axios)将 FormData 发送到服务器。

问题3:Axios.post的语法结构

Axios.post的语法结构,即axios.post(url, data, config),其中data是请求体,config是配置选项。
接下来,要解释每个参数的意义。第一个参数是URL,包含基础地址、路径和token查询参数。第二个参数formData是发送的数据,对应请求体。第三个参数config是Axios的配置对象,比如设置请求头或上传进度回调。


如果不使用Axios.post的语法结构来发送请求,而是用我们封装好的Axios函数来做,来发送请求该如何做

封装好的Axios函数: request_name( )来发送post请求

import Axios from "axios";
import _config from "../conf/confg";
import qs from "qs"; //这里的post数据类型转换我们用拦截器来做
//导出名叫request_name的一个方法
export function request_name(config1 = {}, router) {
  //创建实例
  let service = Axios.create({ baseURL: _config.baseApi });

  //-------------------------------------------------------------------------------
  //请求拦截器来做post数据转换
  service.interceptors.request.use(
    (config) => {
      console.log(config);
----------------------------------------------------------------------
      if (config.method.toLocaleLowerCase() === "post") {  //小写一致化
        config.data = qs.stringify(config.data);
      } else if (config.method.toLocaleLowerCase() === "file") {
        config.method = "post";
        let formData = new FormData();
        if (config.data instanceof Object) { //(config.data是否为对象类型
          for (let key in config.data) {
            formData.append(key, config.data[key]);
          }
          config.data = formData;
        }
-------------------------------------------------------------------
        // config.method = "post";
      }
      return config;
    },

    (error) => {
      return Promise.reject(error);
    }
  );
  //-------------------------------------------------------------------------------

  //响应拦截器
  service.interceptors.response.use(
    (response) => {
      console.log(response); //判断是否调用了会员安全认证接口了
      if (response.config.url == "/home/user/safe?token=1ec949a15fb709370f") {
        if (response.data.code != 200) {
          localStorage.clear();
          //没有调用了会员安全认证接口,即登录验证失败
          router.replace("/login"); //跳到登录页面
        }
      }
      return response;
    },
    (error) => {
      return Promise.reject(error);
    }
  );
  //------------------------------------------------------------------------------
  return service.request(config1).then((res) => res.data);
}

<template>
  <div>
    <div>
      <input type="file" @change="uploadfile" />
      <div class="prog_wrap">
        <div class="text">{{progVal}}%</div>
        <!--  进度百分比 -->
        <div class="proing" :style="{width:progVal+'%'}"></div>
        <!--进度条 -->
      </div>
    </div>
    <div>图片预览效果:<img :src="showImage" alt="" /></div>
  </div>
</template>

<script>




export default{
    name:'up_loadfile',
    data(){
        return  {
            progVal:0,
            showImage:""
        }
    },
   methods:{
    uploadfile(e){

        console.log(e.target.files[0])
        let file=e.target.files[0];

      
---------------------------------------------------------------------------
          this.$requestname({
            url:"/user/myinfo/formdatahead?token="+this.$config.token,
            data:{headfile:file},//由于是post请求,而requestname封装的Axios需要转换数据类型,但在这里的数据类型不需要转
            method:"file",//所以这里的请求类型我们要自定义一个,来逃避Axios中post需要换数据类型这一行为
 进度条      onUploadProgress: (progressEvent)=>{
              let percentCompleted = Math.round( (progressEvent.loaded * 100) / progressEvent.total );
               console.log(percentCompleted);//如果图片上传成功则控制台显示100%
               this.progVal=percentCompleted
            }


          }).then(res=>{
                console.log(res)
                if(res.code==200){
                 	this.showImage="http://vueshop.glbuys.com/userfiles/head/"+res.data.msbox;
                }
                   })


    }
   }
-------------------------------------------------
}
</script>

<style>
.prog_wrap{ width: 300px; height: 40px; border: 1px solid black; position: relative;}
.text{ position: absolute;top: 50%;left: 50%; transform:translate(-50%,-50%);}
.proing{ width: 0%; height: 100%; background-color: aquamarine;}
</style>

如果config.data是Object类型,我们进行for循环,因为,data里面可能还有其他的值呢,如 data:{headfile:file ,“book”:33 }等,很幸运我们这里就有一个值
在这里插入图片描述

FormData 对象的创建和将图片文件添加到 中FormData 对象,如下
在这里插入图片描述
【 FormData 对象的创建和将图片文件添加到 中FormData 对象,】这一步可以放到Axios的请求数据体里,使其更加方便
在这里插入图片描述
在这里插入图片描述

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值