mirror of
https://gitee.com/vant-contrib/vant.git
synced 2025-04-06 03:57:59 +08:00
[new feature] Uploader: add preview prop
This commit is contained in:
parent
39339fdda7
commit
03af04e81e
@ -19,6 +19,10 @@
|
|||||||
|
|
||||||
- 支持`Number`类型的`input-width`属性
|
- 支持`Number`类型的`input-width`属性
|
||||||
|
|
||||||
|
##### Uploader
|
||||||
|
|
||||||
|
- 新增`preview`属性
|
||||||
|
|
||||||
|
|
||||||
### [v2.0.0-beta.3](https://github.com/youzan/vant/tree/v2.0.0-beta.3)
|
### [v2.0.0-beta.3](https://github.com/youzan/vant/tree/v2.0.0-beta.3)
|
||||||
`2019-05-31`
|
`2019-05-31`
|
||||||
|
@ -1,7 +1,7 @@
|
|||||||
<template>
|
<template>
|
||||||
<demo-section>
|
<demo-section>
|
||||||
<demo-block :title="$t('basicUsage')">
|
<demo-block :title="$t('basicUsage')">
|
||||||
<van-uploader />
|
<van-uploader preview />
|
||||||
</demo-block>
|
</demo-block>
|
||||||
|
|
||||||
<demo-block :title="$t('uploadStyle')">
|
<demo-block :title="$t('uploadStyle')">
|
||||||
|
@ -13,7 +13,7 @@ Vue.use(Uploader);
|
|||||||
### Basic Usage
|
### Basic Usage
|
||||||
|
|
||||||
```html
|
```html
|
||||||
<van-uploader :after-read="onRead" />
|
<van-uploader preview :after-read="onRead" />
|
||||||
```
|
```
|
||||||
|
|
||||||
```javascript
|
```javascript
|
||||||
@ -42,6 +42,7 @@ export default {
|
|||||||
|------|------|------|------|
|
|------|------|------|------|
|
||||||
| name | Input name | `String` | - |
|
| name | Input name | `String` | - |
|
||||||
| accept | Accepted file type | `String` | `image/*` |
|
| accept | Accepted file type | `String` | `image/*` |
|
||||||
|
| preview | Whether to show image preview | `Boolean` | `false` |
|
||||||
| multiple | Whether to enable multiple selection pictures | `Boolean` | `false` |
|
| multiple | Whether to enable multiple selection pictures | `Boolean` | `false` |
|
||||||
| disabled | Whether to disabled the upload | `Boolean` | `false` |
|
| disabled | Whether to disabled the upload | `Boolean` | `false` |
|
||||||
| capture | Capture,can be set to `camera` | `String` | - |
|
| capture | Capture,can be set to `camera` | `String` | - |
|
||||||
|
@ -1,5 +1,6 @@
|
|||||||
import { use } from '../utils';
|
import { use } from '../utils';
|
||||||
import Icon from '../icon';
|
import Icon from '../icon';
|
||||||
|
import Image from '../image';
|
||||||
|
|
||||||
const [sfc, bem] = use('uploader');
|
const [sfc, bem] = use('uploader');
|
||||||
|
|
||||||
@ -7,6 +8,7 @@ export default sfc({
|
|||||||
inheritAttrs: false,
|
inheritAttrs: false,
|
||||||
|
|
||||||
props: {
|
props: {
|
||||||
|
preview: Boolean,
|
||||||
disabled: Boolean,
|
disabled: Boolean,
|
||||||
uploadText: String,
|
uploadText: String,
|
||||||
beforeRead: Function,
|
beforeRead: Function,
|
||||||
@ -25,6 +27,12 @@ export default sfc({
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
|
||||||
|
data() {
|
||||||
|
return {
|
||||||
|
previewImages: []
|
||||||
|
};
|
||||||
|
},
|
||||||
|
|
||||||
computed: {
|
computed: {
|
||||||
detail() {
|
detail() {
|
||||||
return {
|
return {
|
||||||
@ -89,48 +97,79 @@ export default sfc({
|
|||||||
if (oversize) {
|
if (oversize) {
|
||||||
this.$emit('oversize', files, this.detail);
|
this.$emit('oversize', files, this.detail);
|
||||||
} else {
|
} else {
|
||||||
this.afterRead && this.afterRead(files, this.detail);
|
if (Array.isArray(files)) {
|
||||||
|
files.forEach(this.addPreviewImage);
|
||||||
|
} else {
|
||||||
|
this.addPreviewImage(files);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (this.afterRead) {
|
||||||
|
this.afterRead(files, this.detail);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
this.resetInput();
|
this.resetInput();
|
||||||
},
|
},
|
||||||
|
|
||||||
|
addPreviewImage(file) {
|
||||||
|
this.previewImages.push(file.content);
|
||||||
|
},
|
||||||
|
|
||||||
resetInput() {
|
resetInput() {
|
||||||
|
/* istanbul ignore else */
|
||||||
if (this.$refs.input) {
|
if (this.$refs.input) {
|
||||||
this.$refs.input.value = '';
|
this.$refs.input.value = '';
|
||||||
}
|
}
|
||||||
|
},
|
||||||
|
|
||||||
|
renderPreview() {
|
||||||
|
if (this.preview) {
|
||||||
|
return this.previewImages.map(image => (
|
||||||
|
<Image fit="cover" class={bem('preview')} src={image} />
|
||||||
|
));
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
|
||||||
render(h) {
|
renderUpload() {
|
||||||
const { slots, accept, disabled, uploadText } = this;
|
const slot = this.slots();
|
||||||
|
|
||||||
function Upload() {
|
const Input = (
|
||||||
const slot = slots();
|
<input
|
||||||
|
{...{ attrs: this.$attrs }}
|
||||||
|
ref="input"
|
||||||
|
type="file"
|
||||||
|
accept={this.accept}
|
||||||
|
class={bem('input')}
|
||||||
|
disabled={this.disabled}
|
||||||
|
onChange={this.onChange}
|
||||||
|
/>
|
||||||
|
);
|
||||||
|
|
||||||
if (slot) {
|
if (slot) {
|
||||||
return slot;
|
return (
|
||||||
|
<div class={bem('input-wrapper')}>
|
||||||
|
{slot}
|
||||||
|
{Input}
|
||||||
|
</div>
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div class={bem('upload')}>
|
<div class={bem('upload')}>
|
||||||
<Icon name="plus" class={bem('upload-icon')} />
|
<Icon name="plus" class={bem('upload-icon')} />
|
||||||
{uploadText && <span class={bem('upload-text')}>{uploadText}</span>}
|
{this.uploadText && <span class={bem('upload-text')}>{this.uploadText}</span>}
|
||||||
|
{Input}
|
||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
},
|
||||||
|
|
||||||
|
render(h) {
|
||||||
return (
|
return (
|
||||||
<div class={bem()}>
|
<div class={bem()}>
|
||||||
{Upload()}
|
<div class={bem('wrapper')}>
|
||||||
<input
|
{this.renderPreview()}
|
||||||
{...{ attrs: this.$attrs }}
|
{this.renderUpload()}
|
||||||
ref="input"
|
</div>
|
||||||
type="file"
|
|
||||||
accept={accept}
|
|
||||||
class={bem('input')}
|
|
||||||
disabled={disabled}
|
|
||||||
onChange={this.onChange}
|
|
||||||
/>
|
|
||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
@ -4,6 +4,11 @@
|
|||||||
position: relative;
|
position: relative;
|
||||||
display: inline-block;
|
display: inline-block;
|
||||||
|
|
||||||
|
&__wrapper {
|
||||||
|
display: flex;
|
||||||
|
flex-wrap: wrap;
|
||||||
|
}
|
||||||
|
|
||||||
&__input {
|
&__input {
|
||||||
position: absolute;
|
position: absolute;
|
||||||
top: 0;
|
top: 0;
|
||||||
@ -13,9 +18,14 @@
|
|||||||
overflow: hidden; // to clip file-upload-button
|
overflow: hidden; // to clip file-upload-button
|
||||||
cursor: pointer;
|
cursor: pointer;
|
||||||
opacity: 0;
|
opacity: 0;
|
||||||
|
|
||||||
|
&-wrapper {
|
||||||
|
position: relative;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
&__upload {
|
&__upload {
|
||||||
|
position: relative;
|
||||||
display: flex;
|
display: flex;
|
||||||
flex-direction: column;
|
flex-direction: column;
|
||||||
align-items: center;
|
align-items: center;
|
||||||
@ -23,6 +33,7 @@
|
|||||||
box-sizing: border-box;
|
box-sizing: border-box;
|
||||||
width: 80px;
|
width: 80px;
|
||||||
height: 80px;
|
height: 80px;
|
||||||
|
margin: 0 10px 10px 0;
|
||||||
background-color: @white;
|
background-color: @white;
|
||||||
border: 1px dashed @gray-light;
|
border: 1px dashed @gray-light;
|
||||||
|
|
||||||
@ -37,4 +48,10 @@
|
|||||||
font-size: 12px;
|
font-size: 12px;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
&__preview {
|
||||||
|
width: 80px;
|
||||||
|
height: 80px;
|
||||||
|
margin: 0 10px 10px 0;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -4,15 +4,21 @@ exports[`renders demo correctly 1`] = `
|
|||||||
<div>
|
<div>
|
||||||
<div>
|
<div>
|
||||||
<div class="van-uploader">
|
<div class="van-uploader">
|
||||||
|
<div class="van-uploader__wrapper">
|
||||||
<div class="van-uploader__upload"><i class="van-icon van-icon-plus van-uploader__upload-icon">
|
<div class="van-uploader__upload"><i class="van-icon van-icon-plus van-uploader__upload-icon">
|
||||||
<!----></i></div><input type="file" accept="image/*" class="van-uploader__input">
|
<!----></i><input type="file" accept="image/*" class="van-uploader__input"></div>
|
||||||
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div>
|
<div>
|
||||||
<div class="van-uploader"><button class="van-button van-button--primary van-button--normal"><i class="van-icon van-icon-photo van-button__icon">
|
<div class="van-uploader">
|
||||||
|
<div class="van-uploader__wrapper">
|
||||||
|
<div class="van-uploader__input-wrapper"><button class="van-button van-button--primary van-button--normal"><i class="van-icon van-icon-photo van-button__icon">
|
||||||
<!----></i><span class="van-button__text">
|
<!----></i><span class="van-button__text">
|
||||||
上传图片
|
上传图片
|
||||||
</span></button><input type="file" accept="image/*" class="van-uploader__input"></div>
|
</span></button><input type="file" accept="image/*" class="van-uploader__input"></div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
`;
|
`;
|
||||||
|
23
packages/uploader/test/__snapshots__/index.spec.js.snap
Normal file
23
packages/uploader/test/__snapshots__/index.spec.js.snap
Normal file
@ -0,0 +1,23 @@
|
|||||||
|
// Jest Snapshot v1, https://goo.gl/fbAQLP
|
||||||
|
|
||||||
|
exports[`render preview image 1`] = `
|
||||||
|
<div class="van-uploader">
|
||||||
|
<div class="van-uploader__wrapper">
|
||||||
|
<div class="van-image van-uploader__preview"><img src="test" class="van-image__img" style="object-fit: cover;">
|
||||||
|
<div class="van-image__loading"><i class="van-icon van-icon-photo-o" style="font-size: 22px;">
|
||||||
|
<!----></i></div>
|
||||||
|
</div>
|
||||||
|
<div class="van-uploader__upload"><i class="van-icon van-icon-plus van-uploader__upload-icon">
|
||||||
|
<!----></i><input type="file" accept="image/*" class="van-uploader__input"></div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
`;
|
||||||
|
|
||||||
|
exports[`render upload-text 1`] = `
|
||||||
|
<div class="van-uploader">
|
||||||
|
<div class="van-uploader__wrapper">
|
||||||
|
<div class="van-uploader__upload"><i class="van-icon van-icon-plus van-uploader__upload-icon">
|
||||||
|
<!----></i><span class="van-uploader__upload-text">Text</span><input type="file" accept="image/*" class="van-uploader__input"></div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
`;
|
@ -113,3 +113,26 @@ test('file size overlimit', async () => {
|
|||||||
await later();
|
await later();
|
||||||
expect(wrapper.emitted('oversize')[2]).toBeFalsy();
|
expect(wrapper.emitted('oversize')[2]).toBeFalsy();
|
||||||
});
|
});
|
||||||
|
|
||||||
|
it('render upload-text', () => {
|
||||||
|
const wrapper = mount(Uploader, {
|
||||||
|
propsData: {
|
||||||
|
uploadText: 'Text'
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
expect(wrapper).toMatchSnapshot();
|
||||||
|
});
|
||||||
|
|
||||||
|
it('render preview image', async () => {
|
||||||
|
const wrapper = mount(Uploader, {
|
||||||
|
propsData: {
|
||||||
|
preview: true
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
wrapper.vm.onChange(file);
|
||||||
|
await later();
|
||||||
|
|
||||||
|
expect(wrapper).toMatchSnapshot();
|
||||||
|
});
|
||||||
|
@ -13,7 +13,7 @@ Vue.use(Uploader);
|
|||||||
### 基础用法
|
### 基础用法
|
||||||
|
|
||||||
```html
|
```html
|
||||||
<van-uploader :after-read="onRead" />
|
<van-uploader preview :after-read="onRead" />
|
||||||
```
|
```
|
||||||
|
|
||||||
```javascript
|
```javascript
|
||||||
@ -42,6 +42,7 @@ export default {
|
|||||||
|------|------|------|------|------|
|
|------|------|------|------|------|
|
||||||
| name | 标识符,可以在回调函数的第二项参数中获取 | `String` | - | 1.6.13 |
|
| name | 标识符,可以在回调函数的第二项参数中获取 | `String` | - | 1.6.13 |
|
||||||
| accept | 接受的文件类型 | `String` | `image/*` | - |
|
| accept | 接受的文件类型 | `String` | `image/*` | - |
|
||||||
|
| preview | 是否在上传完成后展示预览图 | `Boolean` | `false` | 2.0.0 |
|
||||||
| multiple | 是否开启图片多选,部分安卓机型不支持 | `Boolean` | `false` | 2.0.0 |
|
| multiple | 是否开启图片多选,部分安卓机型不支持 | `Boolean` | `false` | 2.0.0 |
|
||||||
| disabled | 是否禁用图片上传 | `Boolean` | `false` | - |
|
| disabled | 是否禁用图片上传 | `Boolean` | `false` | - |
|
||||||
| capture | 图片选取模式,可选值为`camera`(直接调起摄像头) | `String` | - | 2.0.0 |
|
| capture | 图片选取模式,可选值为`camera`(直接调起摄像头) | `String` | - | 2.0.0 |
|
||||||
|
Loading…
x
Reference in New Issue
Block a user