我们晓得 React 的规范形式是单向数据流,而其表单项平常须要监听 onChange 事宜,然后经由过程转变外部的 value 往返写表单项的 value,比如以下 input
class App extends React.Component {
constructor( props ) {
super( props );
this.state = {
inputValue: 'default'
}
this.inputChangeHandler = ( e )=>{
this.setState( {
inputValue: e.target.value
} );
}
}
render() {
return (
<div>
<form>
<input
value={ this.state.inputValue }
onChange={ this.inputChangeHandler }
/>
</form>
</div>
)
}
}
假如表单有许多表单项,那末这类规范的做法须要你写许多个 state 的属性和许多个 onChange 监听函数,这是一个膂力活儿。然则平常的表单运用实在不须要及时监控表单项的用户输入,用 defaultValue 足以,在表单项目 onBlur 或许末了提交的时刻一次考证猎取用户输入即可,比如:
class App extends React.Component {
constructor( props ) {
super( props );
this.submit = ( e )=>{
let userInputValue = this.refs.userInput.value;
// 1. 考证 userInputValue
// 2. 提交表单
}
}
render() {
return (
<div>
<form>
<input
ref="userInput"
defaultValue="default"
/>
<button onClick={ this.submit }>提交</button>
</form>
</div>
)
}
}
如许就可以够少写不少代码,固然你能够写一些东西去批量增加一切的 onChange 事宜监听函数和对应的 state 的属性,比如 redux-form。(转头一想,这类写法在提交时刻也须要写许多猎取用户输入的代码,假如运用第一种正形式,那末提交时刻只须要猎取 state 就可以够了,不过这里先不议论这些)<br/>
关于一个表单而言,平常还须要重置功用(reset),假如是第一种正形式的写法,我们只需保留一份初始化的默认值,在用户点击到了重置后,经由过程 setState 设归去就好了。然则假如运用第二种 defaultValue 的写法,那末就没有办法了,由于 defaultValue 只在第一次建立假造 dom 的时刻有作用,假如 dom 不转变你转变 defaultValue 是没有效的。这个时刻该怎么办呢?<br/>
嘿嘿!这个时刻我们就可以够用到这个奇技淫巧了。既然 defaultValue 是在建立假造 dom 的时刻有效,那末我们在用户点击重置的时刻让 React 从新建立这些表单项的假造 dom 不就好了么。依据 React 假造 dom diff 的算法,只需转变 dom 节点的范例就可以促使在 diff 的时刻从新建立假造 dom。详细的写法我们就用代码来演示下:
class App extends React.Component {
constructor( props ) {
super( props );
// fieldSetWrapperType 是一个标志位属性,render 中会依据这个变量的值的差别,衬着差别的元素
this.fieldSetWrapperType = 'div';
this.submit = ( e )=>{
let userInputValue = this.refs.userInput.value;
// 1. 考证 userInputValue
// 2. 提交表单
}
this.reset = ()=>{
// 点击重置,转变标志位
this.fieldSetWrapperType = this.fieldSetWrapperType === 'div' ? 'section' : 'div';
// 强迫革新这个组件
this.forceUpdate();
}
}
// 把表单项的衬着笼统到一个要领中,防止反复编码
renderFieldSet() {
return (
<input
ref="userInput"
defaultValue="default"
/>
);
}
render() {
return (
<div>
<form>
{
/* 依据 fieldSetWrapperType 值的差别,衬着差别的元素(表单项的 wrapper 元素) */
this.fieldSetWrapperType === 'div' ?
<div className="wrapper">{ this.renderFieldSet() }</div>
:
<section className="wrapper">{ this.renderFieldSet() }</section>
}
<button onClick={ this.submit }>提交</button>
<button onClick={ this.reset }>重置</button>
</form>
</div>
)
}
}
思绪就是在表单项外面包一层元素,每次点击重置后转变一个变量,再强迫革新这个组件,组件依据这个变量差别的值把这个包装元素的 type 转变,那末它下面的一切表单项的假造 dom 都会被从新建立,达到了重置的目标。不过这个结果依赖于 React 假造dom diff 算法。假如今后算法转变了,那末能够就失效了,而且这个写法是反形式的,我初志是想在处置惩罚巨型表单时刻少写点代码偷懒用。假如运用时刻涌现什么副作用,鄙人概不负责。
此技能在写文章时 React 正处于 15.4.x 的版本