SoFunction
Updated on 2025-04-11

Interpreting the issue of uploading vant's Uploader

Uploader upload of vant

The interaction of the vant uploader component is that a series of callback functions will be triggered after clicking upload. If you want to implement the pop-up prompt first when clicking the uploader, and then upload the file after selecting OK.

Generally speaking, wrap an element outside the uploader component, and then set the component to disable mode. When the external element state changes, change the disabled value of the component, and then use the choiceFile provided by vant to obtain the Uploader instance through ref and call the instance method to re-activate the file selection.

The main steps are as follows

First, we can wrap a layer of div outside the uploader component

    <span
      @click="handleClick"
      v-if="isconfirm"
      class="message"
    ></span>
    <van-uploader
      v-model="fileList"
      :after-read="afterRead"
      :disabled="isconfirm"
      ref="uploadImg"
    />

Then define it in data and methods

data() {
    return {
      fileList: [],
      isconfirm: true
 };
  methods: {
    handleClick() {
      this.$dialog
        .confirm({
          message: "test,test,test"
        })
        .then(() => {
           = false;
          this.$();
        })
        .catch(() => {
           = true;
        });
    },
  }

When you see this, please note that the version supported by the choiceFile method is v2.5.6 or above. If there is no effect, first check whether the version you installed meets the requirements.

After checking, the version also meets the requirements, but this.$() just has no effect. What's going on?

It turns out that it is related to the browser execution mechanism event loop. Whenever the choicefile is executed, the component is still in disabled mode and cannot be adjusted. In fact, the isconfirm state has not changed yet, so the selection of the file is not visible. You can use a setTimeout or this.$nextTick() in vue to solve it.

setTimeout(() => {
    this.$();
 }, 0);
 
this.$nextTick(() => {
     this.$();
});

Uploader image compression for vant file upload

Why compress the picture?

With the development of technology, mobile phone pixels are getting better and better, and the pictures taken are getting clearer and clearer. The clearer the picture, the larger the volume. When the mobile terminal uploads a large image, it will stutter and the request timeout will occur.

When the picture is too large, the image preview will also be very slow, so the picture needs to be compressed when the picture is uploaded.

Uploader does not support image compression in the file upload component in the vant, because there are multiple places in the business scenario that need to compress the image when uploading images, so I encapsulated a new component based on the Uploader.

Uploader component encapsulation

This component encapsulates Uploader based on vant file

API

Attribute name Attribute description default value

quality

Compression quality [0-1] 0.5

compressSwitch

Whether to enable compression false

threshold

Compression starts to reach this size [500k] 500

Please refer to the Uploader attribute for Vant file uploadvant official website

Template section

<template>
    <van-uploader :fileList="$" :before-read="beforeReadFn" v-bind="$attrs" v-on="$listeners"/>
</template>

Javascript part

export default {
  name: 'van-small-upload',
  props: {
    quality:{
      type:Number,
      default:0.1
    },
    compressSwitch:{
      type:Boolean,
      default:false
    },
    threshold:{
      type:Number,
      default:500
    },
    beforeRead:{
      type: Function,
      default:()=&gt;true
    }
  },
  data() {
    return {
 
    }
  },
  methods: {
    // Process pictures    imgPreview(file,index) {
      ('Processing pictures Fn...');
      let self = this
      // See if the FileReader is supported or not      if (!file || !) return;
      const size = /1024
      (`Image size ===&gt; ${/1024}k`);
      ('Image compression:',?'open':'close');
      ('Image compression threshold:',+'k');
      ('Image compression reduces frame value:',);
      if (/^image/.test() &amp;&amp; size &gt;=  &amp;&amp; ) {
        // Create a reader        let reader = new FileReader()
        // Convert picture 2 to base64 format        (file)
        // Callback after successful reading         = function() {
          let result = 
          let img = new Image()
           = result
           = function() {
            // Compression            let data = (img,,)
            (`After compression ===&gt;${/1024}k`);
            self.$[index].content = data.base64Data
            self.$[index].file = 
          }
        }
      }
    },
    // Compress pictures    compress(img, name, type) {
      let canvas = ('canvas')
      let ctx = ('2d')
      //Tile canvas      let tCanvas = ('canvas')
      let tctx = ('2d')
      // let initSize = ;
      let width = 
      let height = 
      //If the image is larger than four million pixels, calculate the compression ratio and press the size to below 4 million      let ratio
      if ((ratio = (width * height) / 4000000) &gt; 1) {
        // ("Greater than 4 million pixels");        ratio = (ratio)
        width /= ratio
        height /= ratio
      } else {
        ratio = 1
      }
       = width
       = height
      //      Back color       = '#fff'
      (0, 0, , )
      //If the pixels of the picture are greater than 1 million, use tile painting      let count
      if ((count = (width * height) / 1000000) &gt; 1) {
        // ("More than 100W pixels");        count = ~~((count) + 1) // Calculate how many pieces of tiles to be divided into        //       Calculate the width and height of each tile        let nw = ~~(width / count)
        let nh = ~~(height / count)
         = nw
         = nh
        for (let i = 0; i &lt; count; i++) {
          for (let j = 0; j &lt; count; j++) {
            (img, i * nw * ratio, j * nh * ratio, nw * ratio, nh * ratio, 0, 0, nw, nh)
            (tCanvas, i * nw, j * nh, nw, nh)
          }
        }
      } else {
        (img, 0, 0, width, height)
      }
      //Compress      let ndata = ('image/jpeg', )
       =  =  =  = 0;
      return {base64Data:ndata,fileData:(ndata,name,type)}
    },
    //Convert base64 to file    dataURLtoFile(dataurl,name,type) {
      name = name ? name : 'picture'
      type = type ? type : 'jpg'
      var arr = (','),
        bstr = atob(arr[1]),
        n = ,
        u8arr = new Uint8Array(n)
      while (n--) {
        u8arr[n] = (n)
      }
      return new File([u8arr], name, {
        type: type
      })
    },
    beforeReadFn(file,detail){
      const {index} = detail
      (file,index)
      return (...arguments);
    }
  },
  mounted(){
    
  }
};

Example of usage

<SmUpload v-model="fileList" :before-read="beforeRead" :compressSwitch="true" :quality="0.5"/>

The above is personal experience. I hope you can give you a reference and I hope you can support me more.