公众号:程序员波波
文件选择器是我们经常会使用到的,一般都是通过点击某个按钮然后选取文件。
所以封装一个文件选择按钮还是有必要的。
首先,这个按钮使用起来必须和普通按钮一模一样,否则就失去了封装的意义。
其次也要基本符合我[基础]中讲到的几点。
于是(注意在chrome中使用image/*会很慢):(基础版本)
import React, { PureComponent } from 'react';
import CSSModules from 'react-css-modules';
import Tools from '../../common_js/Tools'
import styles from './FileButton.css'
class FileButton extends PureComponent {
constructor(props) {
super(props);
this.getFiles = this.getFiles.bind(this)
this.onChange = this.onChange.bind(this)
}
getFiles() {
let ans = []
let files = this.refs.fileLoader.files
for (let i = 0; i < files.length; i++) {
ans.push(files[i])
}
return ans
}
onChange(e) {
if (!Tools.isNone(this.props.onChange)) {
this.props.onChange(this.getFiles())
}
this.refs.fileLoader.value = ''
}
render() {
let accept = this.props.accept
if (Tools.isNone(accept)) {
accept = 'image/*'
if (Tools.isChrome()) {
accept = 'image/jpeg,image/gif,image/png,image/bmp'
}
}
return (
<label className={this.props.className} style={this.props.style} >
{this.props.children}
{
this.props.multiple == true ?
<input styleName='input-area' ref='fileLoader' onChange={this.onChange} type="file" accept={accept} multiple />
:
<input styleName='input-area' ref='fileLoader' onChange={this.onChange} type="file" accept={accept} />
}
</label>
);
}
}
export default CSSModules(FileButton, styles);
input_area样式:
.input-area {
width: 0px;
height: 0px;
position:absolute;
clip:rect(0 0 0 0);
}
此外:(@material-ui中Button的封装版本)
import React, { PureComponent } from 'react';
import CSSModules from 'react-css-modules';
import Button from '@material-ui/core/Button';
import Tools from '../../../common_js/Tools'
import styles from './FileButton.css'
class FileButton extends PureComponent {
constructor(props) {
super(props);
this.getFiles = this.getFiles.bind(this)
this.onChange = this.onChange.bind(this)
}
getFiles() {
let ans = []
let files = this.refs.fileLoader.files
for (let i = 0; i < files.length; i++) {
ans.push(files[i])
}
return ans
}
onChange(e) {
if (!Tools.isNone(this.props.onChange)) {
this.props.onChange(this.getFiles())
}
this.refs.fileLoader.value = ''
}
render() {
let {accept, onChange, children, multiple, ...other} = this.props
if (Tools.isNone(accept)) {
accept = 'image/*'
if (Tools.isChrome()) {
accept = 'image/jpeg,image/gif,image/png,image/bmp'
}
}
return (
<Button component='label' {...other} >
{
this.props.multiple == true ?
<input styleName='input-area' ref='fileLoader' onChange={this.onChange} type="file" accept={accept} multiple />
:
<input styleName='input-area' ref='fileLoader' onChange={this.onChange} type="file" accept={accept} />
}
{this.props.children}
</Button>
);
}
}
export default CSSModules(FileButton, styles);