Vant3 Uploader 文件上傳

2021-09-09 16:51 更新

介紹

用于將本地的圖片或文件上傳至服務(wù)器,并在上傳過程中展示預(yù)覽圖和上傳進(jìn)度。目前 Uploader 組件不包含將文件上傳至服務(wù)器的接口邏輯,該步驟需要自行實(shí)現(xiàn)。

實(shí)例演示

引入

通過以下方式來全局注冊(cè)組件,更多注冊(cè)方式請(qǐng)參考組件注冊(cè)。

import { createApp } from 'vue';
import { Uploader } from 'vant';

const app = createApp();
app.use(Uploader);

代碼演示

基礎(chǔ)用法

文件上傳完畢后會(huì)觸發(fā) after-read 回調(diào)函數(shù),獲取到對(duì)應(yīng)的 file 對(duì)象。

<van-uploader :after-read="afterRead" />
export default {
  setup() {
    const afterRead = (file) => {
      // 此時(shí)可以自行將文件上傳至服務(wù)器
      console.log(file);
    };

    return {
      afterRead,
    };
  },
};

文件預(yù)覽

通過 v-model 可以綁定已經(jīng)上傳的文件列表,并展示文件列表的預(yù)覽圖。

<van-uploader v-model="fileList" multiple />
import { ref } from 'vue';

export default {
  setup() {
    const fileList = ref([
      { url: 'https://img.yzcdn.cn/vant/leaf.jpg' },
      // Uploader 根據(jù)文件后綴來判斷是否為圖片文件
      // 如果圖片 URL 中不包含類型信息,可以添加 isImage 標(biāo)記來聲明
      { url: 'https://cloud-image', isImage: true },
    ]);

    return {
      fileList,
    };
  },
};

上傳狀態(tài)

通過 status 屬性可以標(biāo)識(shí)上傳狀態(tài),uploading 表示上傳中,failed 表示上傳失敗,done 表示上傳完成。

<van-uploader v-model="fileList" :after-read="afterRead" />
import { ref } from 'vue';

export default {
  setup() {
    const fileList = ref([
      {
        url: 'https://img.yzcdn.cn/vant/leaf.jpg',
        status: 'uploading',
        message: '上傳中...',
      },
      {
        url: 'https://img.yzcdn.cn/vant/tree.jpg',
        status: 'failed',
        message: '上傳失敗',
      },
    ]);

    const afterRead = (file) => {
      file.status = 'uploading';
      file.message = '上傳中...';

      setTimeout(() => {
        file.status = 'failed';
        file.message = '上傳失敗';
      }, 1000);
    };

    return {
      fileList,
      afterRead,
    };
  },
};

限制上傳數(shù)量

通過 max-count 屬性可以限制上傳文件的數(shù)量,上傳數(shù)量達(dá)到限制后,會(huì)自動(dòng)隱藏上傳區(qū)域。

<van-uploader v-model="fileList" multiple :max-count="2" />
import { ref } from 'vue';

export default {
  setup() {
    const fileList = ref([]);

    return {
      fileList,
    };
  },
};

限制上傳大小

通過 max-size 屬性可以限制上傳文件的大小,超過大小的文件會(huì)被自動(dòng)過濾,這些文件信息可以通過 oversize 事件獲取。

<van-uploader multiple :max-size="500 * 1024" @oversize="onOversize" />
import { Toast } from 'vant';

export default {
  setup() {
    const onOversize = (file) => {
      console.log(file);
      Toast('文件大小不能超過 500kb');
    };

    return {
      onOversize,
    };
  },
};

如果需要針對(duì)不同類型的文件來作出不同的大小限制,可以在 max-size 屬性中傳入一個(gè)函數(shù),在函數(shù)中通過 file.type 區(qū)分文件類型,返回 true 表示超出限制,false 表示未超出限制。

<van-uploader multiple :max-size="isOverSize" />
import { Toast } from 'vant';

export default {
  setup() {
    const isOverSize = (file) => {
      const maxSize = file.type === 'image/jpeg' ? 500 * 1024 : 1000 * 1024;
      return file.size >= maxSize;
    };
    return {
      isOverSize,
    };
  },
};

自定義上傳樣式

通過默認(rèn)插槽可以自定義上傳區(qū)域的樣式。

<van-uploader>
  <van-button icon="plus" type="primary">上傳文件</van-button>
</van-uploader>

自定義預(yù)覽樣式

通過 preview-cover 插槽可以自定義覆蓋在預(yù)覽區(qū)域上方的內(nèi)容。

<van-uploader v-model="fileList">
  <template #preview-cover="{ file }">
    <div class="preview-cover van-ellipsis">{{ file.name }}</div>
  </template>
</van-uploader>

<style>
  .preview-cover {
    position: absolute;
    bottom: 0;
    box-sizing: border-box;
    width: 100%;
    padding: 4px;
    color: #fff;
    font-size: 12px;
    text-align: center;
    background: rgba(0, 0, 0, 0.3);
  }
</style>

上傳前置處理

通過傳入 beforeRead 函數(shù)可以在上傳前進(jìn)行校驗(yàn)和處理,返回 true 表示校驗(yàn)通過,返回 false 表示校驗(yàn)失敗。支持返回 Promise 對(duì) file 對(duì)象進(jìn)行自定義處理,例如壓縮圖片。

<van-uploader :before-read="beforeRead" />
import { Toast } from 'vant';

export default {
  setup() {
    // 返回布爾值
    const beforeRead = (file) => {
      if (file.type !== 'image/jpeg') {
        Toast('請(qǐng)上傳 jpg 格式圖片');
        return false;
      }
      return true;
    };

    // 返回 Promise
    const asyncBeforeRead = (file) => {
      return new Promise((resolve, reject) => {
        if (file.type !== 'image/jpeg') {
          Toast('請(qǐng)上傳 jpg 格式圖片');
          reject();
        } else {
          const img = new File(['foo'], 'bar.jpg', {
            type: 'image/jpeg',
          });
          resolve(img);
        }
      });
    };

    return {
      beforeRead,
      asyncBeforeRead,
    };
  },
};

禁用文件上傳

通過 disabled 屬性禁用文件上傳。

<van-uploader disabled />

自定義單個(gè)圖片預(yù)覽

在 v-model 數(shù)組中設(shè)置單個(gè)預(yù)覽圖片屬性,支持 imageFit deletable previewSize beforeDelete。

<van-uploader v-model="fileList" :deletable="false" />
import { ref } from 'vue';
import { Toast } from 'vant';

export default {
  setup() {
    const fileList = ref([
      { url: 'https://img.yzcdn.cn/vant/leaf.jpg' },
      {
        url: 'https://img.yzcdn.cn/vant/sand.jpg',
        deletable: true,
        beforeDelete: () => {
          Toast('自定義單個(gè)預(yù)覽圖片的事件和樣式');
        },
      },
      {
        url: 'https://img.yzcdn.cn/vant/tree.jpg',
        deletable: true,
        imageFit: 'contain',
        previewSize: 120,
      },
    ]);

    return { fileList };
  },
};

API

Props

參數(shù) 說明 類型 默認(rèn)值
v-model 已上傳的文件列表 FileListItem[] -
accept 允許上傳的文件類型,詳細(xì)說明 string image/*
name 標(biāo)識(shí)符,可以在回調(diào)函數(shù)的第二項(xiàng)參數(shù)中獲取 number | string -
preview-size 預(yù)覽圖和上傳區(qū)域的尺寸,默認(rèn)單位為 px number | string 80px
preview-image 是否在上傳完成后展示預(yù)覽圖 boolean true
preview-full-image 是否在點(diǎn)擊預(yù)覽圖后展示全屏圖片預(yù)覽 boolean true
preview-options 全屏圖片預(yù)覽的配置項(xiàng),可選值見 ImagePreview object -
multiple 是否開啟圖片多選,部分安卓機(jī)型不支持 boolean false
disabled 是否禁用文件上傳 boolean false
readonly v3.1.5 是否將上傳區(qū)域設(shè)置為只讀狀態(tài) boolean false
deletable 是否展示刪除按鈕 boolean true
show-upload 是否展示上傳區(qū)域 boolean true
lazy-load 是否開啟圖片懶加載,須配合 Lazyload 組件使用 boolean false
capture 圖片選取模式,可選值為 camera (直接調(diào)起攝像頭) string -
after-read 文件讀取完成后的回調(diào)函數(shù) Function -
before-read 文件讀取前的回調(diào)函數(shù),返回 false 可終止文件讀取,
支持返回 Promise
Function -
before-delete 文件刪除前的回調(diào)函數(shù),返回 false 可終止文件讀取,
支持返回 Promise
Function -
max-size v3.0.17 文件大小限制,單位為 byte number | string | (file: File) => boolean -
max-count 文件上傳數(shù)量限制 number | string -
result-type 文件讀取結(jié)果類型,可選值為 file text string dataUrl
upload-text 上傳區(qū)域文字提示 string -
image-fit 預(yù)覽圖裁剪模式,可選值見 Image 組件 string cover
upload-icon 上傳區(qū)域圖標(biāo)名稱或圖片鏈接 string photograph
注意:accept、capture 和 multiple 為瀏覽器 input 標(biāo)簽的原生屬性,移動(dòng)端各種機(jī)型對(duì)這些屬性的支持程度有所差異,因此在不同機(jī)型和 WebView 下可能出現(xiàn)一些兼容性問題。

Events

事件名 說明 回調(diào)參數(shù)
oversize 文件大小超過限制時(shí)觸發(fā) 同 after-read
click-upload v3.1.5 點(diǎn)擊上傳區(qū)域時(shí)觸發(fā) event: MouseEvent
click-preview 點(diǎn)擊預(yù)覽圖時(shí)觸發(fā) 同 after-read
close-preview 關(guān)閉全屏圖片預(yù)覽時(shí)觸發(fā) -
delete 刪除文件預(yù)覽時(shí)觸發(fā) 同 after-read

Slots

名稱 說明 參數(shù)
default 自定義上傳區(qū)域 -
preview-cover 自定義覆蓋在預(yù)覽區(qū)域上方的內(nèi)容 item: FileListItem

回調(diào)參數(shù)

before-read、after-read、before-delete 執(zhí)行時(shí)會(huì)傳遞以下回調(diào)參數(shù):

參數(shù)名 說明 類型
file file 對(duì)象 object
detail 額外信息,包含 name 和 index 字段 object

ResultType 可選值

result-type 字段表示文件讀取結(jié)果的類型,上傳大文件時(shí),建議使用 file 類型,避免卡頓。

描述
file 結(jié)果僅包含 File 對(duì)象
text 結(jié)果包含 File 對(duì)象,以及文件的文本內(nèi)容
dataUrl 結(jié)果包含 File 對(duì)象,以及文件對(duì)應(yīng)的 base64 編碼

方法

通過 ref 可以獲取到 Uploader 實(shí)例并調(diào)用實(shí)例方法,詳見組件實(shí)例方法。

方法名 說明 參數(shù) 返回值
closeImagePreview 關(guān)閉全屏的圖片預(yù)覽 - -
chooseFile 主動(dòng)調(diào)起文件選擇,由于瀏覽器安全限制,只有在用戶觸發(fā)操作的上下文中調(diào)用才有效 - -

類型定義

通過 UploaderInstance 獲取 Uploader 實(shí)例的類型定義。

import { ref } from 'vue';
import type { UploaderInstance } from 'vant';

const uploaderRef = ref<UploaderInstance>();

uploaderRef.value?.chooseFile();

樣式變量

組件提供了下列 CSS 變量,可用于自定義樣式,使用方法請(qǐng)參考  ConfigProvider 組件

名稱 默認(rèn)值 描述
--van-uploader-size 80px -
--van-uploader-icon-size 24px -
--van-uploader-icon-color var(--van-gray-4) -
--van-uploader-text-color var(--van-gray-6) -
--van-uploader-text-font-size var(--van-font-size-sm) -
--van-uploader-upload-background-color var(--van-gray-1) -
--van-uploader-upload-active-color var(--van-active-color) -
--van-uploader-delete-color var(--van-white) -
--van-uploader-delete-icon-size 14px -
--van-uploader-delete-background-color rgba(0, 0, 0, 0.7) -
--van-uploader-file-background-color var(--van-background-color) -
--van-uploader-file-icon-size 20px -
--van-uploader-file-icon-color var(--van-gray-7) -
--van-uploader-file-name-padding 0 var(--van-padding-base) -
--van-uploader-file-name-margin-top var(--van-padding-xs) -
--van-uploader-file-name-font-size var(--van-font-size-sm) -
--van-uploader-file-name-text-color var(--van-gray-7) -
--van-uploader-mask-text-color var(--van-white) -
--van-uploader-mask-background-color fade(var(--van-gray-8), 88%) -
--van-uploader-mask-icon-size 22px -
--van-uploader-mask-message-font-size var(--van-font-size-sm) -
--van-uploader-mask-message-line-height var(--van-line-height-xs) -
--van-uploader-loading-icon-size 22px -
--van-uploader-loading-icon-color var(--van-white) -
--van-uploader-disabled-opacity var(--van-disabled-opacity) -

常見問題

拍照上傳的圖片被旋轉(zhuǎn) 90 度?

部分手機(jī)在拍照上傳時(shí)會(huì)出現(xiàn)圖片被旋轉(zhuǎn) 90 度的問題,這個(gè)問題可以通過 compressorjs 或其他開源庫進(jìn)行處理。

compressorjs 是一個(gè)開源的圖片處理庫,提供了圖片壓縮、圖片旋轉(zhuǎn)等能力。

示例

使用 compressorjs 進(jìn)行處理的示例代碼如下:

<van-uploader :before-read="beforeRead" />
import Compressor from 'compressorjs';

export default {
  setup() {
    const beforeRead = (file) => {
      return new Promise((resolve) => {
        // compressorjs 默認(rèn)開啟 checkOrientation 選項(xiàng)
        // 會(huì)將圖片修正為正確方向
        new Compressor(file, {
          success: resolve,
          error(err) {
            console.log(err.message);
          },
        });
      });
    };

    return {
      beforeRead,
    };
  },
};

上傳 HEIC/HEIF 格式的圖片后無法展示?

目前 Chrome、Safari 等瀏覽器不支持展示 HEIC/HEIF 格式的圖片,因此上傳后無法在 Uploader 組件中進(jìn)行預(yù)覽。

[HEIF] 格式的兼容性請(qǐng)參考 caniuse。


以上內(nèi)容是否對(duì)您有幫助:
在線筆記
App下載
App下載

掃描二維碼

下載編程獅App

公眾號(hào)
微信公眾號(hào)

編程獅公眾號(hào)