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')">
|
||||
<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-uploader>
|
||||
</div>
|
||||
|
@ -30,10 +30,10 @@ export default {
|
||||
```
|
||||
|
||||
#### 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
|
||||
<van-uploader :afterRead="logContent" accept="image/gif, image/jpeg">
|
||||
<van-uploader :afterRead="logContent" accept="image/gif, image/jpeg" multiple>
|
||||
<van-icon name="photograph" />
|
||||
</van-uploader>
|
||||
```
|
||||
|
@ -28,10 +28,10 @@ export default {
|
||||
```
|
||||
|
||||
#### 设置 Input 属性
|
||||
可以直接在 Uploader 上设置 accpet 等原生属性,input 会自动继承该属性
|
||||
可以直接在 Uploader 上设置 accpet、multiple 等原生属性,input 会自动继承该属性
|
||||
|
||||
```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-uploader>
|
||||
```
|
||||
|
@ -7,7 +7,7 @@
|
||||
class="van-uploader__input"
|
||||
v-bind="$attrs"
|
||||
:disabled="disabled"
|
||||
@change="onValueChange"
|
||||
@change="onChange"
|
||||
/>
|
||||
</div>
|
||||
</template>
|
||||
@ -29,30 +29,52 @@ export default create({
|
||||
},
|
||||
|
||||
methods: {
|
||||
onValueChange(event) {
|
||||
if (this.disabled) {
|
||||
onChange(event) {
|
||||
let { files } = event.target;
|
||||
if (this.disabled || !files.length) {
|
||||
return;
|
||||
}
|
||||
|
||||
const file = event.target.files[0];
|
||||
if (!file || (this.beforeRead && !this.beforeRead(file))) {
|
||||
files = files.length === 1 ? files[0] : [].slice.call(files, 0);
|
||||
if (!files || (this.beforeRead && !this.beforeRead(files))) {
|
||||
return;
|
||||
}
|
||||
|
||||
const reader = new FileReader();
|
||||
reader.onload = (e) => {
|
||||
this.afterRead && this.afterRead({
|
||||
file,
|
||||
content: e.target.result
|
||||
if (Array.isArray(files)) {
|
||||
Promise.all(files.map(this.readFile)).then(contents => {
|
||||
this.onAfterRead(
|
||||
files.map((file, index) => ({
|
||||
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 { mount } from 'avoriaz';
|
||||
|
||||
window.File = function() {
|
||||
this.name = 'test';
|
||||
};
|
||||
|
||||
window.FileReader = function() {
|
||||
this.readAsDataURL = this.readAsText = function() {
|
||||
this.onload && this.onload({
|
||||
@ -12,97 +14,91 @@ window.FileReader = function() {
|
||||
});
|
||||
};
|
||||
};
|
||||
|
||||
const mockFile = new File([], '/Users');
|
||||
|
||||
describe('Uploader', () => {
|
||||
let wrapper;
|
||||
afterEach(() => {
|
||||
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', () => {
|
||||
const afterRead = sinon.spy();
|
||||
wrapper = mount(Uploader, {
|
||||
propsData: {
|
||||
disabled: true
|
||||
disabled: true,
|
||||
afterRead
|
||||
}
|
||||
});
|
||||
|
||||
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', () => {
|
||||
const afterRead = sinon.spy();
|
||||
wrapper = mount(Uploader, {
|
||||
propsData: {
|
||||
disabled: false,
|
||||
beforeRead: () => {
|
||||
return false;
|
||||
}
|
||||
beforeRead: () => false,
|
||||
afterRead
|
||||
}
|
||||
});
|
||||
|
||||
expect(wrapper.contains('input')).to.equal(true);
|
||||
expect(wrapper.vm.onValueChange({ target: { files: [new File([], '')] }})).to.equal(undefined);
|
||||
wrapper.vm.onChange({ target: { files: [mockFile] }});
|
||||
expect(afterRead.calledOnce).to.be.false;
|
||||
});
|
||||
|
||||
it('read text', () => {
|
||||
it('read text', done => {
|
||||
wrapper = mount(Uploader, {
|
||||
propsData: {
|
||||
disabled: false,
|
||||
resultType: 'text',
|
||||
afterRead: (file) => {
|
||||
expect(file.content).to.equal('test');
|
||||
done();
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
expect(wrapper.contains('input')).to.equal(true);
|
||||
expect(wrapper.vm.onValueChange({ target: { files: [new File([], '/Users')] }})).to.equal(undefined);
|
||||
wrapper.vm.onChange({ target: { files: [mockFile] }});
|
||||
});
|
||||
|
||||
it('read text no after hook', () => {
|
||||
it('read dataUrl', done => {
|
||||
wrapper = mount(Uploader, {
|
||||
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) => {
|
||||
expect(file.content).to.equal('test');
|
||||
done();
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
expect(wrapper.contains('input')).to.equal(true);
|
||||
expect(wrapper.vm.onValueChange({ target: { files: [new File([], '/Users')] }})).to.equal(undefined);
|
||||
wrapper.vm.onChange({ target: { files: [mockFile] }});
|
||||
});
|
||||
|
||||
it('unknown resultType', () => {
|
||||
const afterRead = sinon.spy();
|
||||
wrapper = mount(Uploader, {
|
||||
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);
|
||||
expect(wrapper.vm.onValueChange({ target: { files: [new File([], '/Users')] }})).to.equal(undefined);
|
||||
wrapper.vm.onChange({ target: { files: [mockFile, mockFile] }});
|
||||
});
|
||||
});
|
||||
|
Loading…
x
Reference in New Issue
Block a user