用于將本地的圖片或文件上傳至服務器,并在上傳過程中展示預覽圖和上傳進度。目前 Uploader 組件不包含將文件上傳至服務器的接口邏輯,該步驟需要自行實現(xiàn)。
通過以下方式來全局注冊組件,更多注冊方式請參考組件注冊。
import { createApp } from 'vue';
import { Uploader } from 'vant';
const app = createApp();
app.use(Uploader);
文件上傳完畢后會觸發(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,
};
},
};
通過 ?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,
};
},
};
通過 ?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 };
},
};
參數(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)一些兼容性問題。
事件名 | 說明 | 回調(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
|
名稱 | 說明 | 參數(shù) |
---|---|---|
default | 自定義上傳區(qū)域 | - |
preview-delete v3.5.0
|
自定義刪除按鈕 | - |
preview-cover | 自定義覆蓋在預覽區(qū)域上方的內(nèi)容 | item: FileListItem |
before-read、after-read、before-delete 執(zhí)行時會傳遞以下回調(diào)參數(shù):
參數(shù)名 | 說明 | 類型 |
---|---|---|
file | file 對象 | object |
detail | 額外信息,包含 name 和 index 字段 | object |
?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 采用了 HTML 原生的 ?<input type="file />
? 標簽進行上傳,能否上傳取決于當前系統(tǒng)和瀏覽器的兼容性。當遇到無法上傳的問題時,一般有以下幾種情況:
webp
? 或 ?heic
? 格式。部分手機在拍照上傳時會出現(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)象一般是內(nèi)存不足導致的,通常發(fā)生在舊機型上;上傳一張較大的圖片引起也引起此現(xiàn)象。
為了減少這種情況的出現(xiàn),可以在上傳圖片前對圖片進行壓縮,壓縮方法請參考上文中提到的 ?compressorjs
? 庫。
目前 Chrome、Safari 等瀏覽器不支持展示 HEIC/HEIF 格式的圖片,因此上傳后無法在 Uploader 組件中進行預覽。
[HEIF] 格式的兼容性請參考 caniuse。
更多建議: