Vant4 Uploader 文件上傳

2023-02-16 17:55 更新

介紹

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

引入

通過以下方式來全局注冊組件,更多注冊方式請參考組件注冊。

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

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

代碼演示

基礎(chǔ)用法

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

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

    return {
      afterRead,
    };
  },
};

文件預覽

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

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

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

    return {
      fileList,
    };
  },
};

上傳狀態(tài)

通過 ?status? 屬性可以標識上傳狀態(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://fastly.jsdelivr.net/npm/@vant/assets/leaf.jpeg',
        status: 'uploading',
        message: '上傳中...',
      },
      {
        url: 'https://fastly.jsdelivr.net/npm/@vant/assets/tree.jpeg',
        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ù)量達到限制后,會自動隱藏上傳區(qū)域。

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

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

    return {
      fileList,
    };
  },
};

限制上傳大小

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

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

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

    return {
      onOversize,
    };
  },
};

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

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

自定義上傳樣式

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

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

自定義預覽樣式

通過 ?preview-cover? 插槽可以自定義覆蓋在預覽區(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>

自定義預覽大小

通過 ?preview-size? 屬性定義預覽圖和上傳區(qū)域的大小。

<!-- 不指定單位,默認為 px -->
<van-uploader v-model="fileList" preview-size="60" />
<!-- 指定單位,支持 rem, vh, vw -->
<van-uploader v-model="fileList" preview-size="5rem" />

將 ?preview-size? 設(shè)置為數(shù)組格式,可以分別設(shè)置寬高。數(shù)組第一項對應寬度,數(shù)組第二項對應高度。

<van-uploader v-model="fileList" :preview-size="[60, 40]" />

上傳前置處理

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

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

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

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

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

禁用文件上傳

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

<van-uploader disabled />

自定義單個圖片預覽

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

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

export default {
  setup() {
    const fileList = ref([
      {
        url: 'https://fastly.jsdelivr.net/npm/@vant/assets/sand.jpeg',
        deletable: true,
        beforeDelete: () => {
          showToast('刪除前置處理');
        },
      },
      {
        url: 'https://fastly.jsdelivr.net/npm/@vant/assets/tree.jpeg',
        imageFit: 'contain',
      },
    ]);

    return { fileList };
  },
};

API

Props

參數(shù) 說明 類型 默認值
v-model 已上傳的文件列表 FileListItem[] -
accept 允許上傳的文件類型,詳細說明 string image/*
name 標識符,通常為一個唯一的字符串或數(shù)字,可以在回調(diào)函數(shù)的第二項參數(shù)中獲取 number | string -
preview-size 預覽圖和上傳區(qū)域的尺寸,默認單位為 px number | string | Array 80px
preview-image 是否在上傳完成后展示預覽圖 boolean true
preview-full-image 是否在點擊預覽圖后展示全屏圖片預覽 boolean true
preview-options 全屏圖片預覽的配置項,可選值見 ImagePreview object -
multiple 是否開啟圖片多選,部分安卓機型不支持 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 Infinity
max-count 文件上傳數(shù)量限制 number | string Infinity
result-type 文件讀取結(jié)果類型,可選值為 file text string dataUrl
upload-text 上傳區(qū)域文字提示 string -
image-fit 預覽圖裁剪模式,可選值見 Image 組件 string cover
upload-icon 上傳區(qū)域圖標名稱或圖片鏈接,等同于 Icon 組件的 name 屬性 string photograph
注意:accept、capture 和 multiple 為瀏覽器 input 標簽的原生屬性,移動端各種機型對這些屬性的支持程度有所差異,因此在不同機型和 WebView 下可能出現(xiàn)一些兼容性問題。

Events

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

Slots

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

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

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

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

ResultType 可選值

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

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

方法

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

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

類型定義

組件導出以下類型定義:

import type {
  UploaderProps,
  UploaderInstance,
  UploaderResultType,
  UploaderFileListItem,
} from 'vant';

?UploaderInstance? 是組件實例的類型,用法如下:

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

const uploaderRef = ref<UploaderInstance>();

uploaderRef.value?.chooseFile();

主題定制

樣式變量

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

名稱 默認值 描述
--van-uploader-size 80px -
--van-uploader-icon-size 24px -
--van-uploader-icon-color var(--van-gray-4) -
--van-uploader-text-color var(--van-text-color-2) -
--van-uploader-text-font-size var(--van-font-size-sm) -
--van-uploader-upload-background 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 rgba(0, 0, 0, 0.7) -
--van-uploader-file-background var(--van-background) -
--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 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) -

常見問題

Uploader 在部分安卓機型上無法上傳圖片?

Uploader 采用了 HTML 原生的 ?<input type="file />? 標簽進行上傳,能否上傳取決于當前系統(tǒng)和瀏覽器的兼容性。當遇到無法上傳的問題時,一般有以下幾種情況:

  1. 遇到了安卓 App WebView 的兼容性問題,需要在安卓原生代碼中進行兼容,可以參考此文章
  2. 圖片格式不正確,在當前系統(tǒng)/瀏覽器中無法識別,比如 ?webp? 或 ?heic? 格式。
  3. 其他瀏覽器兼容性問題。

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

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

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

示例

使用 compressorjs 進行處理的示例代碼如下:

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

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

    return {
      beforeRead,
    };
  },
};

上傳圖片時出現(xiàn)瀏覽器刷新或卡頓現(xiàn)象?

這種現(xiàn)象一般是內(nèi)存不足導致的,通常發(fā)生在舊機型上;上傳一張較大的圖片引起也引起此現(xiàn)象。

為了減少這種情況的出現(xiàn),可以在上傳圖片前對圖片進行壓縮,壓縮方法請參考上文中提到的 ?compressorjs? 庫。

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

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

[HEIF] 格式的兼容性請參考 caniuse。


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

掃描二維碼

下載編程獅App

公眾號
微信公眾號

編程獅公眾號