<!-- 文件选择组件 -->
<template>
<view>
<view @click="handleSelectFile"> <!-- 指定一个默认插槽sss -->
<slot>选择文件</slot>
</view>
<view id="fileSelectContainer" :prop="fileProps" :change:prop="fileSelectModule.updateFileProps" r-entry />
</view>
</template>
<!-- 逻辑层 -->
<script>
export default {
name: "FileSelect",
components: {},
data() {
return {
fileProps: {
acceptTypes: '.xls,.xlsx',
selectFileTrigger: false,
fileStrType: 'Base64' //Base64、String
}
}
},
onLoad() {},
methods: {
handleUniSelectFile() {
uni.chooseImage({
count: 6, //默认9
sizeType: ['original', 'compressed'], //可以指定是原图还是压缩图,默认二者都有
sourceType: ['album'], //从相册选择
success: function(res) {
console.log("uni.chooseImage", res);
console.log(JSON.stringify(res.tempFilePaths));
}
});
},
updataSelectFileTrigger(selectFileTrigger) {
this.fileProps.selectFileTrigger = selectFileTrigger
},
handleSelectFile() { //选择文件按钮
//通过属性改变,配合模块的:change:prop=触发视图层的事件
this.fileProps.selectFileTrigger = true;
},
// 处理文件选择回调
handleFileSelected(files) {
this.$emit("fileChange", files)
},
}
}
</script>
<!--视图层:使用 RenderJS模块方式进行APP上非图片和视频选择 -->
<script module="fileSelectModule" lang="renderjs">
export default {
data() {
return {
fileInputId: "select-file-input",
fileInput: null,
fileStrType: null //Base64、String
};
},
mounted() {
this.createFileInput(); // 动态创建文件输入元素
console.log('FileSelectModule已挂载');
},
methods: {
createFileInput() { // 创建文件输入元素
const existingInput = document.getElementById(this.fileInputId);
if (existingInput) { // 移除已存在的input元素
existingInput.remove();
}
// 创建新的文件输入元素
this.fileInput = document.createElement('input');
this.fileInput.id = this.fileInputId;
this.fileInput.type = 'file';
this.fileInput.style.display = 'none';
// 添加文件选择事件监听
this.fileInput.addEventListener('change',
(event) => {
this.handleFileChange(event);
});
document.body.appendChild(this.fileInput);
},
handleFileChange(event) { // 文件选择文成
const files = event.target.files;
if (!files) return;
let promiseArr = []
for (let file of files) {
promiseArr.push(this.fileToBase64OrStr(file))
}
Promise.all(promiseArr)
.then(values => {
let tempFilePaths = [];
let tempFiles = []
for (let fileInfo of values) {
tempFilePaths.push(fileInfo.path)
tempFiles.push(fileInfo)
}
let result = {
tempFilePaths,
tempFiles
}
this.$ownerInstance.callMethod('handleFileSelected', result);
})
.catch(err => {
console.log(err);
})
},
triggerFileInput() { // 触发文件输入点击
if (this.fileInput) {
this.fileInput.click(); //触发点击事件,进行文件选择
this.$ownerInstance.callMethod("updataSelectFileTrigger", false) //重置文件选择标识方便下次进行选择
}
},
updateFileProps(newValue, oldValue) { // 更新文件属性
if (newValue && newValue.selectFileTrigger) { // 监听文件选择触发信号
this.fileStrType = newValue.fileStrType || "String"
this.triggerFileInput();
}
},
fileToBase64OrStr(file) { //将文件转场base64
return new Promise((resolve, reject) => {
const reader = new FileReader()
reader.onloadend = () => { //文件读取操作完成时的回调函数
const base64String = reader.result
let result = {
path: base64String,
size: file.size,
name: file.name, //这个属性uni.chooseImage中没有
type: file.type //这个属性uni.chooseImage中没有
}
resolve(result)
}
reader.onerror = (e) => {
reject(3)
}
//Base64、String
if ("Base64" === this.fileStrType) {
reader.readAsDataURL(file) //以URL编码(Base64编码)格式读取文件数据内容
} else {
reader.readAsText(file) //以文本格式读取文件数据内容
}
})
}
}
};
</script>
<style>
</style>
打开文件选择框截图
