在 React 中创建自定义输入类型文件按钮
Posted
技术标签:
【中文标题】在 React 中创建自定义输入类型文件按钮【英文标题】:Creating custom Input type file button in React 【发布时间】:2018-09-08 09:30:18 【问题描述】:我正在尝试创建自定义<input type="file">
上传按钮,上传文件的名称在上传后在按钮本身上可见,在 React 中。我正在创建它作为组件。我发现创建 codepen 演示非常困难,所以我只是在这里上传代码(对此感到抱歉)。
import React, Component, PropTypes from 'react';
import './InputFile.css';
export default class InputFile extends Component
constructor(props: any)
super(props);
this.getUploadedFileName = this.getUploadedFileName.bind(this);
getUploadedFileName(selectorFiles: FileList, props)
const id = this.props;
;( function ( document, window, index )
var inputs = document.querySelectorAll(`#$id`);
Array.prototype.forEach.call( inputs, function( input )
var label = input.nextElementSibling,
labelVal = label.innerhtml;
input.addEventListener( 'change', function( e )
var fileName = '';
if( this.files && this.files.length > 1 )
fileName = ( this.getAttribute( 'data-multiple-caption' ) ||
'' ).replace( 'count', this.files.length );
else
fileName = e.target.value.split( '\\' ).pop();
if( fileName )
label.querySelector( 'span' ).innerHTML = fileName;
else
label.innerHTML = labelVal;
);
// Firefox bug fix
input.addEventListener( 'focus', function() input.classList.add(
'has-focus' ); );
input.addEventListener( 'blur', function() input.classList.remove(
'has-focus' ); );
);
( document, window, 0 ));
render ()
const id, text, multiple = this.props;
return(
<div>
<input id=id type="file" className="km-btn-file" data-multiple-caption="count files selected" multiple=multiple onChange= (e, id) => this.getUploadedFileName(e.target.files, id)></input>
<label htmlFor=id className="km-button km-button--primary km-btn-file-label">
<span>text</span>
</label>
</div>
);
InputFile.propTypes =
id: PropTypes.string.isRequired,
text: PropTypes.string.isRequired,
multiple: PropTypes.string,
;
我正在将这个组件导入我的另一个文件<InputFile id='input-file' text='Upload File' multiple='multiple'/>
这是CSS代码
.km-button--primary
background-color: #5C5AA7;
color: #FFFFFF;
.km-button
border-radius: 3px;
-webkit-appearance: none;
border: none;
outline: none;
background: transparent;
height: 36px;
padding: 0px 16px;
margin: 0;
font-size: 14px;
font-weight: 400;
text-align: center;
min-width: 70px;
transition: all 0.3s ease-out;
.km-btn-file
width: 0.1px;
height: 0.1px;
opacity: 0;
overflow: hidden;
position: absolute;
z-index: -1;
.km-btn-file-label
line-height: 36px;
cursor: pointer;
我面临的问题是,当我第一次单击按钮并选择要上传的文件时,它会选择文件,但不会使用文件名更新文本“上传文件”。但是在第二次点击它之后它工作正常。我不知道为什么会这样,为此我需要帮助。
谢谢。
【问题讨论】:
你应该使用你的生命周期和状态,以便它直接更新它。 【参考方案1】:您可以使用组件“状态”来更新您的元素。
constructor(props: any)
super(props);
this.state = message:'some initial message';
对于 onChange 事件,请执行以下操作:
getUploadedFileName = (e) =>
let files = e.target.files,
value = e.target.value,
message;
if( files && files.length > 1 ) message = `$files.length files selected`;
else message = value.split( '\\' ).pop();
if(message) this.setState(...this.state,message);
然后在元素中将值绑定到状态:
<div>
<input id=id type="file" className="km-btn-file"
data-multiple-caption=this.state.message
multiple=multiple
onChange=this.getUploadedFileName>
</input>
<label htmlFor=id className="km-button km-button--primary km-btn-file-label">
<span>text</span>
</label>
</div>
【讨论】:
我很好用。虽然有一个小修正,但我认为最后一部分<span>text</span>
应该是 <span>this.state.message</span>
。除非我错过了什么。【参考方案2】:
您需要将 props 中的 text 属性绑定到您的状态,因此您必须在构造函数中执行此操作;
this.state = ...props;
或
this.state = text: props.text, id: props.id, multiple: props.multiple ;
然后在要更新视图值时调用,而不是自己手动设置标签上的innerHtml; this.setState(text : 新值);
在你的渲染方法中;
const id, text, multiple = this.state;
当你调用 this.setState 时,它会告诉 React 重新渲染你的组件,然后从状态中获取更新的值。
【讨论】:
它的行为仍然相同。你必须选择文件两次才能进行“文本”更新。以上是关于在 React 中创建自定义输入类型文件按钮的主要内容,如果未能解决你的问题,请参考以下文章