近期有个小H5项目需要接入自有APP中,这个项目中涉及多个图片上传的功能,且使用的是vant 的van-uploader,但发布到APP进行测试时发现上传组件全都没有反应,这可咋整?按vant官方的建议改APP是一种方法,但APP是外包的,改是比较费劲了。那就只能自己动手修改vant了。
目标在vant 对应的组件中增加nativeHandle属性,传入APP 提供的JSAPI,使之能适配APP。
方法1、在gitee上找到vant的源码,clone 2.x分支,git clone -b 2.x --single-branch https://gitee.com/vant-contrib/vant.git
2、找到uploader增加nativeHandle的属性;
3、增加从APP回调的图片base64信息,再转换为File,加入组件原有的处理逻辑。
4、修改后,编译。
直接放代码,(base64转File的方法抄的网上的),直接上代码
代码中中文注释部分为修改过的部分。
// Utils
import { createNamespace, addUnit, noop, isPromise, isDef } from '../utils';
import { toArray, readFile, isOversize, isImageFile } from './utils';
// Mixins
import { FieldMixin } from '../mixins/field';
// Components
import Icon from '../icon';
import Image from '../image';
import Loading from '../loading';
import ImagePreview from '../image-preview';
const [createComponent, bem] = createNamespace('uploader');
export default createComponent({
inheritAttrs: false,
mixins: [FieldMixin],
model: {
prop: 'fileList',
},
props: {
disabled: Boolean,
readonly: Boolean,
lazyLoad: Boolean,
uploadText: String,
afterRead: Function,
beforeRead: Function,
beforeDelete: Function,
previewSize: [Number, String],
previewOptions: Object,
nativeHandle: Function, //增加组件属性
name: {
type: [Number, String],
default: '',
},
accept: {
type: String,
default: 'image/*',
},
fileList: {
type: Array,
default: () => [],
},
maxSize: {
type: [Number, String, Function],
default: Number.MAX_VALUE,
},
maxCount: {
type: [Number, String],
default: Number.MAX_VALUE,
},
deletable: {
type: Boolean,
default: true,
},
showUpload: {
type: Boolean,
default: true,
},
previewImage: {
type: Boolean,
default: true,
},
previewFullImage: {
type: Boolean,
default: true,
},
imageFit: {
type: String,
default: 'cover',
},
resultType: {
type: String,
default: 'dataUrl',
},
uploadIcon: {
type: String,
default: 'photograph',
},
},
computed: {
previewSizeWithUnit() {
return addUnit(this.previewSize);
},
// for form
value() {
return this.fileList;
},
},
created() {
this.urls = [];
},
beforeDestroy() {
this.urls.forEach((url) => URL.revokeObjectURL(url));
},
methods: {
getDetail(index = this.fileList.length) {
return {
name: this.name,
index,
};
},
//增加图片转File流
dataURLtoBlob(dataurl, name, mime) {
const bstr = atob(dataurl);
let n = bstr.length;
const u8arr = new Uint8Array(n);
while (n--) {
u8arr[n] = bstr.charCodeAt(n)
}
return new File([u8arr], name, {
type: mime,
})
},
//增加添加处理方法,
addFile(dataurl, name, mime){
const files = [];
files.push(this.dataURLtoBlob(dataurl,name, mime));
const event = {"target":{"files":files}};
this.onChange(event);
},
onChange(event) {
let { files } = event.target;
if (this.disabled || !files.length) {
return;
}
files = files.length === 1 ? files[0] : [].slice.call(files);
if (this.beforeRead) {
const response = this.beforeRead(files, this.getDetail());
if (!response) {
this.resetInput();
return;
}
if (isPromise(response)) {
response
.then((data) => {
if (data) {
this.readFile(data);
} else {
this.readFile(files);
}
})
.catch(this.resetInput);
return;
}
}
this.readFile(files);
},
readFile(files) {
const oversize = isOversize(files, this.maxSize);
if (Array.isArray(files)) {
const maxCount = this.maxCount - this.fileList.length;
if (files.length > maxCount) {
files = files.slice(0, maxCount);
}
Promise.all(files.map((file) => readFile(file, this.resultType))).then(
(contents) => {
const fileList = files.map((file, index) => {
const result = { file, status: '', message: '' };
if (contents[index]) {
result.content = contents[index];
}
return result;
});
this.onAfterRead(fileList, oversize);
}
);
} else {
readFile(files, this.resultType).then((content) => {
const result = { file: files, status: '', message: '' };
if (content) {
result.content = content;
}
this.onAfterRead(result, oversize);
});
}
},
onAfterRead(files, oversize) {
this.resetInput();
let validFiles = files;
if (oversize) {
let oversizeFiles = files;
if (Array.isArray(files)) {
oversizeFiles = [];
validFiles = [];
files.forEach((item) => {
if (item.file) {
if (isOversize(item.file, this.maxSize)) {
oversizeFiles.push(item);
} else {
validFiles.push(item);
}
}
});
} else {
validFiles = null;
}
this.$emit('oversize', oversizeFiles, this.getDetail());
}
const isValidFiles = Array.isArray(validFiles)
? Boolean(validFiles.length)
: Boolean(validFiles);
if (isValidFiles) {
this.$emit('input', [...this.fileList, ...toArray(validFiles)]);
if (this.afterRead) {
this.afterRead(validFiles, this.getDetail());
}
}
},
onDelete(file, index) {
const beforeDelete = file.beforeDelete ?? this.beforeDelete;
if (beforeDelete) {
const response = beforeDelete(file, this.getDetail(index));
if (!response) {
return;
}
if (isPromise(response)) {
response
.then(() => {
this.deleteFile(file, index);
})
.catch(noop);
return;
}
}
this.deleteFile(file, index);
},
deleteFile(file, index) {
const fileList = this.fileList.slice(0);
fileList.splice(index, 1);
this.$emit('input', fileList);
this.$emit('delete', file, this.getDetail(index));
},
resetInput() {
/* istanbul ignore else */
if (this.$refs.input) {
this.$refs.input.value = '';
}
},
onClickUpload(event) {
this.$emit('click-upload', event);
},
onPreviewImage(item) {
if (!this.previewFullImage) {
return;
}
const imageFiles = this.fileList.filter((item) => isImageFile(item));
const imageContents = imageFiles.map((item) => {
if (item.file && !item.url) {
item.url = URL.createObjectURL(item.file);
this.urls.push(item.url);
}
return item.url;
});
this.imagePreview = ImagePreview({
images: imageContents,
startPosition: imageFiles.indexOf(item),
onClose: () => {
this.$emit('close-preview');
},
...this.previewOptions,
});
},
// @exposed-api
closeImagePreview() {
if (this.imagePreview) {
this.imagePreview.close();
}
},
// @exposed-api
chooseFile() {
if (this.disabled) {
return;
}
/* istanbul ignore else */
if (this.$refs.input) {
this.$refs.input.click();
}
},
genPreviewMask(item) {
const { status, message } = item;
if (status === 'uploading' || status === 'failed') {
const MaskIcon =
status === 'failed' ? (
) : (
);
const showMessage = isDef(message) && message !== '';
return (
{MaskIcon}
{showMessage && {message}}
);
}
},
genPreviewItem(item, index) {
const deleteAble = item.deletable ?? this.deletable;
const showDelete = item.status !== 'uploading' && deleteAble;
const DeleteIcon = showDelete && (
{
event.stopPropagation();
this.onDelete(item, index);
}}
>
);
const PreviewCoverContent = this.slots('preview-cover', {
index,
...item,
});
const PreviewCover = PreviewCoverContent && (
{PreviewCoverContent}
);
const previewSize = item.previewSize ?? this.previewSize;
const imageFit = item.imageFit ?? this.imageFit;
const Preview = isImageFile(item) ? (
{
this.onPreviewImage(item);
}}
>
{PreviewCover}
) : (
{
width: this.previewSizeWithUnit,
height: this.previewSizeWithUnit,
}}
>
{item.file ? item.file.name : item.url}
{PreviewCover}
);
return (
{
this.$emit('click-preview', item, this.getDetail(index));
}}
>
{Preview}
{this.genPreviewMask(item)}
{DeleteIcon}
);
},
genPreviewList() {
if (this.previewImage) {
return this.fileList.map(this.genPreviewItem);
}
},
genUpload() {
if (this.fileList.length >= this.maxCount || !this.showUpload) {
return;
}
const slot = this.slots();
//当有nativeHanle时替换上传按钮的处理方法
const Input = this.readonly ? null : (
this.nativeHandle==null?
:
{this.nativeHandle(this);}}
/>
);
if (slot) {
return (
{slot}
{Input}
);
}
let style;
if (this.previewSize) {
const size = this.previewSizeWithUnit;
style = {
width: size,
height: size,
};
}
return (
{this.uploadText && (
{this.uploadText}
)}
{Input}
);
},
},
render() {
return (
{this.genPreviewList()}
{this.genUpload()}
);
},
});
欢迎分享,转载请注明来源:内存溢出
评论列表(0条)