feat(Uploader): max-size prop can be a function (#8744)

* feat(Uploader): max-size prop can be a function

* chore: revert demo

* test: fix snapshot

* docs: upd
This commit is contained in:
neverland 2021-05-22 20:30:09 +08:00 committed by GitHub
parent 5b6dadc39f
commit 833064adbd
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
5 changed files with 94 additions and 12 deletions

View File

@ -146,6 +146,28 @@ export default {
};
```
If you need to make different size limits for different types of files, you can pass a function to the `max-size` props.
```html
<van-uploader multiple :max-size="isOverSize" />
```
```js
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,
};
},
};
```
### Custom Upload Area
```html
@ -274,7 +296,7 @@ export default {
| name | Input name | _number \| string_ | - |
| preview-size | Size of preview image | _number \| string_ | `80px` |
| preview-image | Whether to show image preview | _boolean_ | `true` |
| preview-full-image | Whethe to show full screen image preview when image is clicked | _boolean_ | `true` |
| preview-full-image | Whether to show full screen image preview when image is clicked | _boolean_ | `true` |
| preview-options | Options of full screen image previewsee [ImagePreview](#/en-US/image-preview) | _object_ | - |
| multiple | Whether to enable multiple selection pictures | _boolean_ | `false` |
| disabled | Whether to disabled the upload | _boolean_ | `false` |
@ -285,7 +307,7 @@ export default {
| after-read | Hook after reading the file | _Function_ | - |
| before-read | Hook before reading the file, return false to stop reading the file, can return Promise | _Function_ | - |
| before-delete | Hook before delete the file, return false to stop reading the file, can return Promise | _Function_ | - |
| max-size | Max size of file | _number \| string_ | - |
| max-size `v3.0.17` | Max size of file | _number \| string \| (file: File) => boolean_ | - |
| max-count | Max count of image | _number \| string_ | - |
| result-type | Type of file read result, can be set to `file` `text` | _string_ | `dataUrl` |
| upload-text | Upload text | _string_ | - |
@ -308,7 +330,7 @@ export default {
| default | Custom icon | - |
| preview-cover | Custom content that covers the image preview | `item: FileListItem` |
### Parematers of before-read、after-read、before-delete
### Parameters of before-read、after-read、before-delete
| Attribute | Description | Type |
| --------- | ------------------------------------ | -------- |

View File

@ -159,6 +159,28 @@ export default {
};
```
如果需要针对不同类型的文件来作出不同的大小限制,可以在 `max-size` 属性中传入一个函数,在函数中通过 `file.type` 区分文件类型,返回 `true` 表示超出限制,`false` 表示未超出限制。
```html
<van-uploader multiple :max-size="isOverSize" />
```
```js
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,
};
},
};
```
### 自定义上传样式
通过默认插槽可以自定义上传区域的样式。
@ -306,7 +328,7 @@ export default {
| after-read | 文件读取完成后的回调函数 | _Function_ | - |
| before-read | 文件读取前的回调函数,返回 `false` 可终止文件读取,<br>支持返回 `Promise` | _Function_ | - |
| before-delete | 文件删除前的回调函数,返回 `false` 可终止文件读取,<br>支持返回 `Promise` | _Function_ | - |
| max-size | 文件大小限制,单位为 `byte` | _number \| string_ | - |
| max-size `v3.0.17` | 文件大小限制,单位为 `byte` | _number \| string \| (file: File) => boolean_ | - |
| max-count | 文件上传数量限制 | _number \| string_ | - |
| result-type | 文件读取结果类型,可选值为 `file` `text` | _string_ | `dataUrl` |
| upload-text | 上传区域文字提示 | _string_ | - |

View File

@ -17,6 +17,7 @@ import {
filterFiles,
isImageFile,
readFileContent,
UploaderMaxSize,
UploaderResultType,
UploaderFileListItem,
} from './utils';
@ -83,7 +84,7 @@ export default defineComponent({
default: () => [],
},
maxSize: {
type: [Number, String],
type: [Number, String, Function] as PropType<UploaderMaxSize>,
default: Number.MAX_VALUE,
},
maxCount: {

View File

@ -3,7 +3,9 @@ import Uploader, { UploaderFileListItem } from '..';
import { mount, later, triggerDrag } from '../../../test';
const mockFileDataUrl = 'data:image/test';
const mockFile = new File([new ArrayBuffer(10000)], 'test.jpg');
const mockFile = new File([new ArrayBuffer(10000)], 'test.jpg', {
type: 'test',
});
const IMAGE = 'https://img.yzcdn.cn/vant/cat.jpeg';
const PDF = 'https://img.yzcdn.cn/vant/test.pdf';
@ -218,7 +220,7 @@ test('before read return promise and reject', async () => {
expect(input.element.value).toEqual('');
});
test('file size overlimit', async () => {
test('should trigger oversize event when file size is overlimit', async () => {
const wrapper = mount(Uploader, {
props: {
maxSize: 1,
@ -250,6 +252,31 @@ test('file size overlimit', async () => {
expect(wrapper.emitted<[File]>('oversize')![2]).toBeFalsy();
});
test('should allow to custom max-size for different type of files', async () => {
const wrapper = mount(Uploader, {
props: {
maxSize(file: File) {
if (file.type === 'test') {
return file.size > 500;
}
return false;
},
},
});
const input = wrapper.find<HTMLInputElement>('.van-uploader__input');
const fileList = [mockFile];
Object.defineProperty(input.element, 'files', {
get: () => jest.fn().mockReturnValue(fileList)(),
});
await input.trigger('change');
await later();
expect(wrapper.emitted<[File]>('oversize')![0]).toBeTruthy();
});
test('render upload-text', () => {
const uploadText = 'Text';
const wrapper = mount(Uploader, {

View File

@ -1,4 +1,4 @@
import { createNamespace } from '../utils';
import { createNamespace, isFunction } from '../utils';
import type { ImageFit } from '../image';
import type { Interceptor } from '../utils/interceptor';
@ -21,6 +21,8 @@ export type UploaderFileListItem = {
beforeDelete?: Interceptor;
};
export type UploaderMaxSize = number | string | ((file: File) => boolean);
export function toArray<T>(item: T | T[]): T[] {
if (Array.isArray(item)) {
return item;
@ -52,20 +54,28 @@ export function readFileContent(file: File, resultType: UploaderResultType) {
export function isOversize(
items: UploaderFileListItem | UploaderFileListItem[],
maxSize: number | string
maxSize: UploaderMaxSize
): boolean {
return toArray(items).some((item) => item.file && item.file.size > maxSize);
return toArray(items).some((item) => {
if (item.file) {
if (isFunction(maxSize)) {
return maxSize(item.file);
}
return item.file.size > maxSize;
}
return false;
});
}
export function filterFiles(
items: UploaderFileListItem[],
maxSize: number | string
maxSize: UploaderMaxSize
) {
const valid: UploaderFileListItem[] = [];
const invalid: UploaderFileListItem[] = [];
items.forEach((item) => {
if (item.file && item.file.size > maxSize) {
if (isOversize(item, maxSize)) {
invalid.push(item);
} else {
valid.push(item);