mirror of
https://gitee.com/vant-contrib/vant.git
synced 2025-04-06 03:57:59 +08:00
[new feature] Uploader: support multiple files (#480)
This commit is contained in:
parent
30f22b28ed
commit
4b0f4ac426
@ -10,7 +10,7 @@
|
|||||||
|
|
||||||
<demo-block :title="$t('title2')">
|
<demo-block :title="$t('title2')">
|
||||||
<div class="demo-uploader-container">
|
<div class="demo-uploader-container">
|
||||||
<van-uploader :after-read="logContent" accept="image/gif, image/jpeg">
|
<van-uploader :after-read="logContent" accept="image/gif, image/jpeg" multiple>
|
||||||
<van-icon name="photograph" />
|
<van-icon name="photograph" />
|
||||||
</van-uploader>
|
</van-uploader>
|
||||||
</div>
|
</div>
|
||||||
|
@ -30,10 +30,10 @@ export default {
|
|||||||
```
|
```
|
||||||
|
|
||||||
#### Set input attr
|
#### Set input attr
|
||||||
You can set native properties such as `accpet` on Uploader, and the input will automatically inherits the attribute.
|
You can set native properties such as `accpet`、`multiple` on Uploader, and the input will automatically inherits the attribute.
|
||||||
|
|
||||||
```html
|
```html
|
||||||
<van-uploader :afterRead="logContent" accept="image/gif, image/jpeg">
|
<van-uploader :afterRead="logContent" accept="image/gif, image/jpeg" multiple>
|
||||||
<van-icon name="photograph" />
|
<van-icon name="photograph" />
|
||||||
</van-uploader>
|
</van-uploader>
|
||||||
```
|
```
|
||||||
|
@ -28,10 +28,10 @@ export default {
|
|||||||
```
|
```
|
||||||
|
|
||||||
#### 设置 Input 属性
|
#### 设置 Input 属性
|
||||||
可以直接在 Uploader 上设置 accpet 等原生属性,input 会自动继承该属性
|
可以直接在 Uploader 上设置 accpet、multiple 等原生属性,input 会自动继承该属性
|
||||||
|
|
||||||
```html
|
```html
|
||||||
<van-uploader :afterRead="logContent" accept="image/gif, image/jpeg">
|
<van-uploader :afterRead="logContent" accept="image/gif, image/jpeg" multiple>
|
||||||
<van-icon name="photograph" />
|
<van-icon name="photograph" />
|
||||||
</van-uploader>
|
</van-uploader>
|
||||||
```
|
```
|
||||||
|
@ -7,7 +7,7 @@
|
|||||||
class="van-uploader__input"
|
class="van-uploader__input"
|
||||||
v-bind="$attrs"
|
v-bind="$attrs"
|
||||||
:disabled="disabled"
|
:disabled="disabled"
|
||||||
@change="onValueChange"
|
@change="onChange"
|
||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
</template>
|
</template>
|
||||||
@ -29,30 +29,52 @@ export default create({
|
|||||||
},
|
},
|
||||||
|
|
||||||
methods: {
|
methods: {
|
||||||
onValueChange(event) {
|
onChange(event) {
|
||||||
if (this.disabled) {
|
let { files } = event.target;
|
||||||
|
if (this.disabled || !files.length) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
const file = event.target.files[0];
|
files = files.length === 1 ? files[0] : [].slice.call(files, 0);
|
||||||
if (!file || (this.beforeRead && !this.beforeRead(file))) {
|
if (!files || (this.beforeRead && !this.beforeRead(files))) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
const reader = new FileReader();
|
if (Array.isArray(files)) {
|
||||||
reader.onload = (e) => {
|
Promise.all(files.map(this.readFile)).then(contents => {
|
||||||
this.afterRead && this.afterRead({
|
this.onAfterRead(
|
||||||
file,
|
files.map((file, index) => ({
|
||||||
content: e.target.result
|
file: files[index],
|
||||||
|
content: contents[index]
|
||||||
|
}))
|
||||||
|
);
|
||||||
|
});
|
||||||
|
} else {
|
||||||
|
this.readFile(files).then(content => {
|
||||||
|
this.onAfterRead({ file: files, content });
|
||||||
});
|
});
|
||||||
this.$refs.input && (this.$refs.input.value = '');
|
|
||||||
};
|
|
||||||
|
|
||||||
if (this.resultType === 'dataUrl') {
|
|
||||||
reader.readAsDataURL(file);
|
|
||||||
} else if (this.resultType === 'text') {
|
|
||||||
reader.readAsText(file);
|
|
||||||
}
|
}
|
||||||
|
},
|
||||||
|
|
||||||
|
readFile(file) {
|
||||||
|
return new Promise(resolve => {
|
||||||
|
const reader = new FileReader();
|
||||||
|
|
||||||
|
reader.onload = event => {
|
||||||
|
resolve(event.target.result);
|
||||||
|
};
|
||||||
|
|
||||||
|
if (this.resultType === 'dataUrl') {
|
||||||
|
reader.readAsDataURL(file);
|
||||||
|
} else if (this.resultType === 'text') {
|
||||||
|
reader.readAsText(file);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
},
|
||||||
|
|
||||||
|
onAfterRead(file) {
|
||||||
|
this.afterRead && this.afterRead(file);
|
||||||
|
this.$refs.input && (this.$refs.input.value = '');
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
@ -1,8 +1,10 @@
|
|||||||
import Uploader from 'packages/uploader';
|
import Uploader from 'packages/uploader';
|
||||||
import { mount } from 'avoriaz';
|
import { mount } from 'avoriaz';
|
||||||
|
|
||||||
window.File = function() {
|
window.File = function() {
|
||||||
this.name = 'test';
|
this.name = 'test';
|
||||||
};
|
};
|
||||||
|
|
||||||
window.FileReader = function() {
|
window.FileReader = function() {
|
||||||
this.readAsDataURL = this.readAsText = function() {
|
this.readAsDataURL = this.readAsText = function() {
|
||||||
this.onload && this.onload({
|
this.onload && this.onload({
|
||||||
@ -12,97 +14,91 @@ window.FileReader = function() {
|
|||||||
});
|
});
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
|
|
||||||
|
const mockFile = new File([], '/Users');
|
||||||
|
|
||||||
describe('Uploader', () => {
|
describe('Uploader', () => {
|
||||||
let wrapper;
|
let wrapper;
|
||||||
afterEach(() => {
|
afterEach(() => {
|
||||||
wrapper && wrapper.destroy();
|
wrapper && wrapper.destroy();
|
||||||
});
|
});
|
||||||
|
|
||||||
it('enabled', () => {
|
|
||||||
wrapper = mount(Uploader, {
|
|
||||||
propsData: {
|
|
||||||
disabled: false
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
expect(wrapper.contains('input')).to.equal(true);
|
|
||||||
expect(wrapper.vm.onValueChange({ target: { files: [] }})).to.equal(undefined);
|
|
||||||
});
|
|
||||||
|
|
||||||
it('disabled', () => {
|
it('disabled', () => {
|
||||||
|
const afterRead = sinon.spy();
|
||||||
wrapper = mount(Uploader, {
|
wrapper = mount(Uploader, {
|
||||||
propsData: {
|
propsData: {
|
||||||
disabled: true
|
disabled: true,
|
||||||
|
afterRead
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
expect(wrapper.contains('input')).to.equal(true);
|
expect(wrapper.contains('input')).to.equal(true);
|
||||||
expect(wrapper.vm.onValueChange({ target: { files: [] }})).to.equal(undefined);
|
wrapper.vm.onChange({ target: { files: [] }});
|
||||||
|
expect(afterRead.calledOnce).to.be.false;
|
||||||
});
|
});
|
||||||
|
|
||||||
it('before read', () => {
|
it('before read', () => {
|
||||||
|
const afterRead = sinon.spy();
|
||||||
wrapper = mount(Uploader, {
|
wrapper = mount(Uploader, {
|
||||||
propsData: {
|
propsData: {
|
||||||
disabled: false,
|
beforeRead: () => false,
|
||||||
beforeRead: () => {
|
afterRead
|
||||||
return false;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
expect(wrapper.contains('input')).to.equal(true);
|
wrapper.vm.onChange({ target: { files: [mockFile] }});
|
||||||
expect(wrapper.vm.onValueChange({ target: { files: [new File([], '')] }})).to.equal(undefined);
|
expect(afterRead.calledOnce).to.be.false;
|
||||||
});
|
});
|
||||||
|
|
||||||
it('read text', () => {
|
it('read text', done => {
|
||||||
wrapper = mount(Uploader, {
|
wrapper = mount(Uploader, {
|
||||||
propsData: {
|
propsData: {
|
||||||
disabled: false,
|
|
||||||
resultType: 'text',
|
resultType: 'text',
|
||||||
afterRead: (file) => {
|
afterRead: (file) => {
|
||||||
|
expect(file.content).to.equal('test');
|
||||||
|
done();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
expect(wrapper.contains('input')).to.equal(true);
|
wrapper.vm.onChange({ target: { files: [mockFile] }});
|
||||||
expect(wrapper.vm.onValueChange({ target: { files: [new File([], '/Users')] }})).to.equal(undefined);
|
|
||||||
});
|
});
|
||||||
|
|
||||||
it('read text no after hook', () => {
|
it('read dataUrl', done => {
|
||||||
wrapper = mount(Uploader, {
|
wrapper = mount(Uploader, {
|
||||||
propsData: {
|
propsData: {
|
||||||
disabled: false,
|
|
||||||
resultType: 'text'
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
expect(wrapper.contains('input')).to.equal(true);
|
|
||||||
expect(wrapper.vm.onValueChange({ target: { files: [new File([], '/Users')] }})).to.equal(undefined);
|
|
||||||
});
|
|
||||||
|
|
||||||
it('read dataUrl', () => {
|
|
||||||
wrapper = mount(Uploader, {
|
|
||||||
propsData: {
|
|
||||||
disabled: false,
|
|
||||||
resultType: 'dataUrl',
|
|
||||||
afterRead: (file) => {
|
afterRead: (file) => {
|
||||||
|
expect(file.content).to.equal('test');
|
||||||
|
done();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
expect(wrapper.contains('input')).to.equal(true);
|
wrapper.vm.onChange({ target: { files: [mockFile] }});
|
||||||
expect(wrapper.vm.onValueChange({ target: { files: [new File([], '/Users')] }})).to.equal(undefined);
|
|
||||||
});
|
});
|
||||||
|
|
||||||
it('unknown resultType', () => {
|
it('unknown resultType', () => {
|
||||||
|
const afterRead = sinon.spy();
|
||||||
wrapper = mount(Uploader, {
|
wrapper = mount(Uploader, {
|
||||||
propsData: {
|
propsData: {
|
||||||
disabled: false,
|
resultType: 'xxxx',
|
||||||
resultType: 'xxxx'
|
afterRead
|
||||||
|
}
|
||||||
|
});
|
||||||
|
wrapper.vm.onChange({ target: { files: [mockFile] }});
|
||||||
|
expect(afterRead.calledOnce).to.be.false;
|
||||||
|
});
|
||||||
|
|
||||||
|
it('read multiple files', done => {
|
||||||
|
wrapper = mount(Uploader, {
|
||||||
|
propsData: {
|
||||||
|
afterRead: (file) => {
|
||||||
|
expect(file.length).to.equal(2);
|
||||||
|
done();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
expect(wrapper.contains('input')).to.equal(true);
|
wrapper.vm.onChange({ target: { files: [mockFile, mockFile] }});
|
||||||
expect(wrapper.vm.onValueChange({ target: { files: [new File([], '/Users')] }})).to.equal(undefined);
|
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
Loading…
x
Reference in New Issue
Block a user