封装一个选取文件的组件。
我们需要的功能只是点击后选择文件,获取文件在本地电脑的绝对路径,然后我们用这个路径自己去上传。
1、结构
1、放一个el-input组件,用于显示选取的文件的路径字符串
element的el-input组件只提供了关于输入文本的功能,没有提供选择文件的功能。
- 设置readonly属性,使它只能用于显示,而不能输入;
- v-model绑定路径字符串
2、第一个el-button组件,是嵌套在el-input的插槽,用于点击后触发选取文件
为它绑定点击事件,添加native事件修饰符,在父组件上点击时,触发的是子组件上的事件。
@click.native="slectPath"
slectPath() {
this.$refs.path.value = "";
this.$refs.path.click();
},
具有选取文件功能的元素只要type="file"的input元素。所以我们借助它来实现文件路径获取。
- 放一个type="file"的input元素,并设置style使它不可见;
- 为它设置一个ref,用于在vue实例中获取它;
- 设置multiple属性,决定选取文件是是否可以多选;
- 为它绑定一个change事件,在选取文件完成后触发。
点击第一个el-button按钮后,调用了this.$refs.path.click(),就相当于点击了这个input元素,从而会打开一个文件选取的对话框。
选取文件后,触发input的change事件
openPath() {
let files=event.target.files;
this.pathArr= Array.prototype.map.call(files,item=>{
return item.path;
})
},
这个事件中,通过event.target.files获取所有选取的文件的路径,这是一个类数组。我们获取每一项中的path,所有的路径都放到了一个数组中;
而el-input显示的只能是字符串,所以我们在计算属性中处理一下路径数组,组成一个字符串去显示。
showPath(){
return this.pathArr.join(',')
}
3、第二个el-button组件,用于点击后触发上传动作
我们不希望选择完文件就直接上传,有可能选了文件暂时还不想上传。
我们为它绑定点击事件。点击后触发自定义事件,在父组件中相应,并把路径数组传过去。父组件响应事件,并且得到数据了,想干嘛干嘛,要上传也好,要展示也好,都与我子组件无关,子组件获取路径的任务已经完成了。
uploadClick() {
if (this.pathArr.length==0) {
this.$message.error("Please select file directory.");
return;
}
this.$emit("upload",this.pathArr);
this.pathArr=[];
},
结构代码。
<template>
<div class="upload-container">
<el-input
readonly
size="mini"
v-model="showPath"
:placeholder="placeholder"
:disabled="disabled"
>
<el-button
size="mini"
slot="append"
icon="el-icon-folder-opened"
@click.native="slectPath"
:disabled="disabled"
></el-button>
</el-input>
<el-button
size="mini"
class="submitbtn"
:disabled="disabled"
@click="uploadClick"
>{{ btnName }}</el-button
>
<input
type="file"
ref="path"
:multiple='multiple'
@change="openPath"
style="
filter: alpha(oonOpenCSVFilepacity=0);
opacity: 0;
width: 0px;
height: 0px;
"
/>
</div>
</template>
2、css
<style scoped>
.upload-container {
display: flex;
align-items: center;
}
.upload-container .el-input {
flex: 1;
}
.upload-container .submitbtn {
margin-left: 10px;
}
</style>