[React 基础系列] 受控表单 vs 不受控表单

  • 受控表单
  • refs
  • 不受控表单
  • 不受控组件
  • 总结

之前的学习部分带了一些表单内容的使用——之前的案例基本上是用的都是 input,接下来就学习一下受控表单和不受控表单之间的区别,并且通过非受控表单了解一下非受控组件的知识点。

受控表单指的是状态由 React 内部进行管理的表单,自然,不受控表单值得就是状态不由 React 内部进行管理的表单。

学习案例下载资源在:受控表单 vs 不受控表单-案例

前复习过的内容:

  • 什么是 JSX,以及如何使用 JSX
  • 元素 vs 组件
  • 状态 & 状态更新 & 生命周期方法
  • 事件处理

受控表单

受控表单指的是所有的表单状态由 state 进行管理的表单,通过 setState 触发状态更新,如下面的这个受控组件:

class ControlledForm extends Component {constructor() {super();this.state = {name: '',phone: '',};this.onSubmit = this.onSubmit.bind(this);}updateInputHandler = (e, label) => {this.setState((prevState) => {return { ...prevState, [label]: e.target.value };});};onSubmit = (e) => {for (const [key, val] of Object.entries(this.state)) {console.log(key, val);}// e.preventDefault(); 放置页面的重定向e.preventDefault();};render() {return (<form onSubmit={this.onSubmit}><div><label>name: </label><inputtype="text"value={this.state.name}onChange={(e) => this.updateInputHandler(e, 'name')}/></div><div><label>phone: </label><inputtype="text"value={this.state.phone}onChange={(e) => this.updateInputHandler(e, 'phone')}/></div><div><input type="submit" value="submit" /></div></form>);}
}

实现效果为:

这里的事件处理通过接收另外一个参数,可以做到简化状态更新的方法。这是利用了 ES6 中的计算属性名的特殊特性去实现的。通过使用 obj[variable] 这种语法可以通过传入参数(variable),做到动态更新参数(variable)的值。

更懂 ES6 的新特性可以参考: 都 2021 年了还不会连 ES6/ES2015 更新了什么都不知道吧 这篇笔记。

另外,注意到这里的 setState 的写法与之前的案例不一样,这是因为 React 更新状态并不能保证是同步地情况。为了节省效率,它内部会判断哪些 setState 是可以合并,放在一个 batch job 里面去更新。所以直接在 setState 调用 this.state 去传值是一个非常危险的行为。而通过 this.setState(prevState => {//...}) 回调函数,能够保证在 setState 内获取的状态,是更新时的状态。

#mermaid-svg-LDPy5DrdGUnkQthS .label{font-family:'trebuchet ms', verdana, arial;font-family:var(--mermaid-font-family);fill:#333;color:#333}#mermaid-svg-LDPy5DrdGUnkQthS .label text{fill:#333}#mermaid-svg-LDPy5DrdGUnkQthS .node rect,#mermaid-svg-LDPy5DrdGUnkQthS .node circle,#mermaid-svg-LDPy5DrdGUnkQthS .node ellipse,#mermaid-svg-LDPy5DrdGUnkQthS .node polygon,#mermaid-svg-LDPy5DrdGUnkQthS .node path{fill:#ECECFF;stroke:#9370db;stroke-width:1px}#mermaid-svg-LDPy5DrdGUnkQthS .node .label{text-align:center;fill:#333}#mermaid-svg-LDPy5DrdGUnkQthS .node.clickable{cursor:pointer}#mermaid-svg-LDPy5DrdGUnkQthS .arrowheadPath{fill:#333}#mermaid-svg-LDPy5DrdGUnkQthS .edgePath .path{stroke:#333;stroke-width:1.5px}#mermaid-svg-LDPy5DrdGUnkQthS .flowchart-link{stroke:#333;fill:none}#mermaid-svg-LDPy5DrdGUnkQthS .edgeLabel{background-color:#e8e8e8;text-align:center}#mermaid-svg-LDPy5DrdGUnkQthS .edgeLabel rect{opacity:0.9}#mermaid-svg-LDPy5DrdGUnkQthS .edgeLabel span{color:#333}#mermaid-svg-LDPy5DrdGUnkQthS .cluster rect{fill:#ffffde;stroke:#aa3;stroke-width:1px}#mermaid-svg-LDPy5DrdGUnkQthS .cluster text{fill:#333}#mermaid-svg-LDPy5DrdGUnkQthS div.mermaidTooltip{position:absolute;text-align:center;max-width:200px;padding:2px;font-family:'trebuchet ms', verdana, arial;font-family:var(--mermaid-font-family);font-size:12px;background:#ffffde;border:1px solid #aa3;border-radius:2px;pointer-events:none;z-index:100}#mermaid-svg-LDPy5DrdGUnkQthS .actor{stroke:#ccf;fill:#ECECFF}#mermaid-svg-LDPy5DrdGUnkQthS text.actor>tspan{fill:#000;stroke:none}#mermaid-svg-LDPy5DrdGUnkQthS .actor-line{stroke:grey}#mermaid-svg-LDPy5DrdGUnkQthS .messageLine0{stroke-width:1.5;stroke-dasharray:none;stroke:#333}#mermaid-svg-LDPy5DrdGUnkQthS .messageLine1{stroke-width:1.5;stroke-dasharray:2, 2;stroke:#333}#mermaid-svg-LDPy5DrdGUnkQthS #arrowhead path{fill:#333;stroke:#333}#mermaid-svg-LDPy5DrdGUnkQthS .sequenceNumber{fill:#fff}#mermaid-svg-LDPy5DrdGUnkQthS #sequencenumber{fill:#333}#mermaid-svg-LDPy5DrdGUnkQthS #crosshead path{fill:#333;stroke:#333}#mermaid-svg-LDPy5DrdGUnkQthS .messageText{fill:#333;stroke:#333}#mermaid-svg-LDPy5DrdGUnkQthS .labelBox{stroke:#ccf;fill:#ECECFF}#mermaid-svg-LDPy5DrdGUnkQthS .labelText,#mermaid-svg-LDPy5DrdGUnkQthS .labelText>tspan{fill:#000;stroke:none}#mermaid-svg-LDPy5DrdGUnkQthS .loopText,#mermaid-svg-LDPy5DrdGUnkQthS .loopText>tspan{fill:#000;stroke:none}#mermaid-svg-LDPy5DrdGUnkQthS .loopLine{stroke-width:2px;stroke-dasharray:2, 2;stroke:#ccf;fill:#ccf}#mermaid-svg-LDPy5DrdGUnkQthS .note{stroke:#aa3;fill:#fff5ad}#mermaid-svg-LDPy5DrdGUnkQthS .noteText,#mermaid-svg-LDPy5DrdGUnkQthS .noteText>tspan{fill:#000;stroke:none}#mermaid-svg-LDPy5DrdGUnkQthS .activation0{fill:#f4f4f4;stroke:#666}#mermaid-svg-LDPy5DrdGUnkQthS .activation1{fill:#f4f4f4;stroke:#666}#mermaid-svg-LDPy5DrdGUnkQthS .activation2{fill:#f4f4f4;stroke:#666}#mermaid-svg-LDPy5DrdGUnkQthS .mermaid-main-font{font-family:"trebuchet ms", verdana, arial;font-family:var(--mermaid-font-family)}#mermaid-svg-LDPy5DrdGUnkQthS .section{stroke:none;opacity:0.2}#mermaid-svg-LDPy5DrdGUnkQthS .section0{fill:rgba(102,102,255,0.49)}#mermaid-svg-LDPy5DrdGUnkQthS .section2{fill:#fff400}#mermaid-svg-LDPy5DrdGUnkQthS .section1,#mermaid-svg-LDPy5DrdGUnkQthS .section3{fill:#fff;opacity:0.2}#mermaid-svg-LDPy5DrdGUnkQthS .sectionTitle0{fill:#333}#mermaid-svg-LDPy5DrdGUnkQthS .sectionTitle1{fill:#333}#mermaid-svg-LDPy5DrdGUnkQthS .sectionTitle2{fill:#333}#mermaid-svg-LDPy5DrdGUnkQthS .sectionTitle3{fill:#333}#mermaid-svg-LDPy5DrdGUnkQthS .sectionTitle{text-anchor:start;font-size:11px;text-height:14px;font-family:'trebuchet ms', verdana, arial;font-family:var(--mermaid-font-family)}#mermaid-svg-LDPy5DrdGUnkQthS .grid .tick{stroke:#d3d3d3;opacity:0.8;shape-rendering:crispEdges}#mermaid-svg-LDPy5DrdGUnkQthS .grid .tick text{font-family:'trebuchet ms', verdana, arial;font-family:var(--mermaid-font-family)}#mermaid-svg-LDPy5DrdGUnkQthS .grid path{stroke-width:0}#mermaid-svg-LDPy5DrdGUnkQthS .today{fill:none;stroke:red;stroke-width:2px}#mermaid-svg-LDPy5DrdGUnkQthS .task{stroke-width:2}#mermaid-svg-LDPy5DrdGUnkQthS .taskText{text-anchor:middle;font-family:'trebuchet ms', verdana, arial;font-family:var(--mermaid-font-family)}#mermaid-svg-LDPy5DrdGUnkQthS .taskText:not([font-size]){font-size:11px}#mermaid-svg-LDPy5DrdGUnkQthS .taskTextOutsideRight{fill:#000;text-anchor:start;font-size:11px;font-family:'trebuchet ms', verdana, arial;font-family:var(--mermaid-font-family)}#mermaid-svg-LDPy5DrdGUnkQthS .taskTextOutsideLeft{fill:#000;text-anchor:end;font-size:11px}#mermaid-svg-LDPy5DrdGUnkQthS .task.clickable{cursor:pointer}#mermaid-svg-LDPy5DrdGUnkQthS .taskText.clickable{cursor:pointer;fill:#003163 !important;font-weight:bold}#mermaid-svg-LDPy5DrdGUnkQthS .taskTextOutsideLeft.clickable{cursor:pointer;fill:#003163 !important;font-weight:bold}#mermaid-svg-LDPy5DrdGUnkQthS .taskTextOutsideRight.clickable{cursor:pointer;fill:#003163 !important;font-weight:bold}#mermaid-svg-LDPy5DrdGUnkQthS .taskText0,#mermaid-svg-LDPy5DrdGUnkQthS .taskText1,#mermaid-svg-LDPy5DrdGUnkQthS .taskText2,#mermaid-svg-LDPy5DrdGUnkQthS .taskText3{fill:#fff}#mermaid-svg-LDPy5DrdGUnkQthS .task0,#mermaid-svg-LDPy5DrdGUnkQthS .task1,#mermaid-svg-LDPy5DrdGUnkQthS .task2,#mermaid-svg-LDPy5DrdGUnkQthS .task3{fill:#8a90dd;stroke:#534fbc}#mermaid-svg-LDPy5DrdGUnkQthS .taskTextOutside0,#mermaid-svg-LDPy5DrdGUnkQthS .taskTextOutside2{fill:#000}#mermaid-svg-LDPy5DrdGUnkQthS .taskTextOutside1,#mermaid-svg-LDPy5DrdGUnkQthS .taskTextOutside3{fill:#000}#mermaid-svg-LDPy5DrdGUnkQthS .active0,#mermaid-svg-LDPy5DrdGUnkQthS .active1,#mermaid-svg-LDPy5DrdGUnkQthS .active2,#mermaid-svg-LDPy5DrdGUnkQthS .active3{fill:#bfc7ff;stroke:#534fbc}#mermaid-svg-LDPy5DrdGUnkQthS .activeText0,#mermaid-svg-LDPy5DrdGUnkQthS .activeText1,#mermaid-svg-LDPy5DrdGUnkQthS .activeText2,#mermaid-svg-LDPy5DrdGUnkQthS .activeText3{fill:#000 !important}#mermaid-svg-LDPy5DrdGUnkQthS .done0,#mermaid-svg-LDPy5DrdGUnkQthS .done1,#mermaid-svg-LDPy5DrdGUnkQthS .done2,#mermaid-svg-LDPy5DrdGUnkQthS .done3{stroke:grey;fill:#d3d3d3;stroke-width:2}#mermaid-svg-LDPy5DrdGUnkQthS .doneText0,#mermaid-svg-LDPy5DrdGUnkQthS .doneText1,#mermaid-svg-LDPy5DrdGUnkQthS .doneText2,#mermaid-svg-LDPy5DrdGUnkQthS .doneText3{fill:#000 !important}#mermaid-svg-LDPy5DrdGUnkQthS .crit0,#mermaid-svg-LDPy5DrdGUnkQthS .crit1,#mermaid-svg-LDPy5DrdGUnkQthS .crit2,#mermaid-svg-LDPy5DrdGUnkQthS .crit3{stroke:#f88;fill:red;stroke-width:2}#mermaid-svg-LDPy5DrdGUnkQthS .activeCrit0,#mermaid-svg-LDPy5DrdGUnkQthS .activeCrit1,#mermaid-svg-LDPy5DrdGUnkQthS .activeCrit2,#mermaid-svg-LDPy5DrdGUnkQthS .activeCrit3{stroke:#f88;fill:#bfc7ff;stroke-width:2}#mermaid-svg-LDPy5DrdGUnkQthS .doneCrit0,#mermaid-svg-LDPy5DrdGUnkQthS .doneCrit1,#mermaid-svg-LDPy5DrdGUnkQthS .doneCrit2,#mermaid-svg-LDPy5DrdGUnkQthS .doneCrit3{stroke:#f88;fill:#d3d3d3;stroke-width:2;cursor:pointer;shape-rendering:crispEdges}#mermaid-svg-LDPy5DrdGUnkQthS .milestone{transform:rotate(45deg) scale(0.8, 0.8)}#mermaid-svg-LDPy5DrdGUnkQthS .milestoneText{font-style:italic}#mermaid-svg-LDPy5DrdGUnkQthS .doneCritText0,#mermaid-svg-LDPy5DrdGUnkQthS .doneCritText1,#mermaid-svg-LDPy5DrdGUnkQthS .doneCritText2,#mermaid-svg-LDPy5DrdGUnkQthS .doneCritText3{fill:#000 !important}#mermaid-svg-LDPy5DrdGUnkQthS .activeCritText0,#mermaid-svg-LDPy5DrdGUnkQthS .activeCritText1,#mermaid-svg-LDPy5DrdGUnkQthS .activeCritText2,#mermaid-svg-LDPy5DrdGUnkQthS .activeCritText3{fill:#000 !important}#mermaid-svg-LDPy5DrdGUnkQthS .titleText{text-anchor:middle;font-size:18px;fill:#000;font-family:'trebuchet ms', verdana, arial;font-family:var(--mermaid-font-family)}#mermaid-svg-LDPy5DrdGUnkQthS g.classGroup text{fill:#9370db;stroke:none;font-family:'trebuchet ms', verdana, arial;font-family:var(--mermaid-font-family);font-size:10px}#mermaid-svg-LDPy5DrdGUnkQthS g.classGroup text .title{font-weight:bolder}#mermaid-svg-LDPy5DrdGUnkQthS g.clickable{cursor:pointer}#mermaid-svg-LDPy5DrdGUnkQthS g.classGroup rect{fill:#ECECFF;stroke:#9370db}#mermaid-svg-LDPy5DrdGUnkQthS g.classGroup line{stroke:#9370db;stroke-width:1}#mermaid-svg-LDPy5DrdGUnkQthS .classLabel .box{stroke:none;stroke-width:0;fill:#ECECFF;opacity:0.5}#mermaid-svg-LDPy5DrdGUnkQthS .classLabel .label{fill:#9370db;font-size:10px}#mermaid-svg-LDPy5DrdGUnkQthS .relation{stroke:#9370db;stroke-width:1;fill:none}#mermaid-svg-LDPy5DrdGUnkQthS .dashed-line{stroke-dasharray:3}#mermaid-svg-LDPy5DrdGUnkQthS #compositionStart{fill:#9370db;stroke:#9370db;stroke-width:1}#mermaid-svg-LDPy5DrdGUnkQthS #compositionEnd{fill:#9370db;stroke:#9370db;stroke-width:1}#mermaid-svg-LDPy5DrdGUnkQthS #aggregationStart{fill:#ECECFF;stroke:#9370db;stroke-width:1}#mermaid-svg-LDPy5DrdGUnkQthS #aggregationEnd{fill:#ECECFF;stroke:#9370db;stroke-width:1}#mermaid-svg-LDPy5DrdGUnkQthS #dependencyStart{fill:#9370db;stroke:#9370db;stroke-width:1}#mermaid-svg-LDPy5DrdGUnkQthS #dependencyEnd{fill:#9370db;stroke:#9370db;stroke-width:1}#mermaid-svg-LDPy5DrdGUnkQthS #extensionStart{fill:#9370db;stroke:#9370db;stroke-width:1}#mermaid-svg-LDPy5DrdGUnkQthS #extensionEnd{fill:#9370db;stroke:#9370db;stroke-width:1}#mermaid-svg-LDPy5DrdGUnkQthS .commit-id,#mermaid-svg-LDPy5DrdGUnkQthS .commit-msg,#mermaid-svg-LDPy5DrdGUnkQthS .branch-label{fill:lightgrey;color:lightgrey;font-family:'trebuchet ms', verdana, arial;font-family:var(--mermaid-font-family)}#mermaid-svg-LDPy5DrdGUnkQthS .pieTitleText{text-anchor:middle;font-size:25px;fill:#000;font-family:'trebuchet ms', verdana, arial;font-family:var(--mermaid-font-family)}#mermaid-svg-LDPy5DrdGUnkQthS .slice{font-family:'trebuchet ms', verdana, arial;font-family:var(--mermaid-font-family)}#mermaid-svg-LDPy5DrdGUnkQthS g.stateGroup text{fill:#9370db;stroke:none;font-size:10px;font-family:'trebuchet ms', verdana, arial;font-family:var(--mermaid-font-family)}#mermaid-svg-LDPy5DrdGUnkQthS g.stateGroup text{fill:#9370db;fill:#333;stroke:none;font-size:10px}#mermaid-svg-LDPy5DrdGUnkQthS g.statediagram-cluster .cluster-label text{fill:#333}#mermaid-svg-LDPy5DrdGUnkQthS g.stateGroup .state-title{font-weight:bolder;fill:#000}#mermaid-svg-LDPy5DrdGUnkQthS g.stateGroup rect{fill:#ECECFF;stroke:#9370db}#mermaid-svg-LDPy5DrdGUnkQthS g.stateGroup line{stroke:#9370db;stroke-width:1}#mermaid-svg-LDPy5DrdGUnkQthS .transition{stroke:#9370db;stroke-width:1;fill:none}#mermaid-svg-LDPy5DrdGUnkQthS .stateGroup .composit{fill:white;border-bottom:1px}#mermaid-svg-LDPy5DrdGUnkQthS .stateGroup .alt-composit{fill:#e0e0e0;border-bottom:1px}#mermaid-svg-LDPy5DrdGUnkQthS .state-note{stroke:#aa3;fill:#fff5ad}#mermaid-svg-LDPy5DrdGUnkQthS .state-note text{fill:black;stroke:none;font-size:10px}#mermaid-svg-LDPy5DrdGUnkQthS .stateLabel .box{stroke:none;stroke-width:0;fill:#ECECFF;opacity:0.7}#mermaid-svg-LDPy5DrdGUnkQthS .edgeLabel text{fill:#333}#mermaid-svg-LDPy5DrdGUnkQthS .stateLabel text{fill:#000;font-size:10px;font-weight:bold;font-family:'trebuchet ms', verdana, arial;font-family:var(--mermaid-font-family)}#mermaid-svg-LDPy5DrdGUnkQthS .node circle.state-start{fill:black;stroke:black}#mermaid-svg-LDPy5DrdGUnkQthS .node circle.state-end{fill:black;stroke:white;stroke-width:1.5}#mermaid-svg-LDPy5DrdGUnkQthS #statediagram-barbEnd{fill:#9370db}#mermaid-svg-LDPy5DrdGUnkQthS .statediagram-cluster rect{fill:#ECECFF;stroke:#9370db;stroke-width:1px}#mermaid-svg-LDPy5DrdGUnkQthS .statediagram-cluster rect.outer{rx:5px;ry:5px}#mermaid-svg-LDPy5DrdGUnkQthS .statediagram-state .divider{stroke:#9370db}#mermaid-svg-LDPy5DrdGUnkQthS .statediagram-state .title-state{rx:5px;ry:5px}#mermaid-svg-LDPy5DrdGUnkQthS .statediagram-cluster.statediagram-cluster .inner{fill:white}#mermaid-svg-LDPy5DrdGUnkQthS .statediagram-cluster.statediagram-cluster-alt .inner{fill:#e0e0e0}#mermaid-svg-LDPy5DrdGUnkQthS .statediagram-cluster .inner{rx:0;ry:0}#mermaid-svg-LDPy5DrdGUnkQthS .statediagram-state rect.basic{rx:5px;ry:5px}#mermaid-svg-LDPy5DrdGUnkQthS .statediagram-state rect.divider{stroke-dasharray:10,10;fill:#efefef}#mermaid-svg-LDPy5DrdGUnkQthS .note-edge{stroke-dasharray:5}#mermaid-svg-LDPy5DrdGUnkQthS .statediagram-note rect{fill:#fff5ad;stroke:#aa3;stroke-width:1px;rx:0;ry:0}:root{--mermaid-font-family: '"trebuchet ms", verdana, arial';--mermaid-font-family: "Comic Sans MS", "Comic Sans", cursive}#mermaid-svg-LDPy5DrdGUnkQthS .error-icon{fill:#522}#mermaid-svg-LDPy5DrdGUnkQthS .error-text{fill:#522;stroke:#522}#mermaid-svg-LDPy5DrdGUnkQthS .edge-thickness-normal{stroke-width:2px}#mermaid-svg-LDPy5DrdGUnkQthS .edge-thickness-thick{stroke-width:3.5px}#mermaid-svg-LDPy5DrdGUnkQthS .edge-pattern-solid{stroke-dasharray:0}#mermaid-svg-LDPy5DrdGUnkQthS .edge-pattern-dashed{stroke-dasharray:3}#mermaid-svg-LDPy5DrdGUnkQthS .edge-pattern-dotted{stroke-dasharray:2}#mermaid-svg-LDPy5DrdGUnkQthS .marker{fill:#333}#mermaid-svg-LDPy5DrdGUnkQthS .marker.cross{stroke:#333}:root { --mermaid-font-family: "trebuchet ms", verdana, arial;} #mermaid-svg-LDPy5DrdGUnkQthS {color: rgba(0, 0, 0, 0.75);font: ;}

未执行
未执行
未执行
未执行
执行,顺序不确定
执行,顺序不确定
执行,顺序不确定
执行,顺序不确定
setState1
setState1
setState2
setState2
setState3
setState3
setState4
setState4
batch Job

按照上面的图示所说,在 setState2 中调用的this.state,极大可能会受到 setState4 的影响,从而造成更新的状态出错。这种合并更新的情况在大型应用中经常会发生,所以必须要注意这点。

确实受控组件写起来会有点麻烦,尤其是之后如果需要加其他的类型检查,那么 updateInputHandler 里面的内容会变得非常的多,这也是下一步会实现优化/封装的内容题材。

refs

refs 其实是一种可以在 React 中更直接访问 DOM 节点,或在 render 方法中创建 React 元素的方法。它的出现是针对于在组件中可能需要在非常规操作的 React 时所实用的方法。

回顾一下,常规方法即组件内通过 state 管理,父子组件通过 props 传递信息。自然,非常规方法就是不通过 state 也不通过 props 去对组件 和/或 元素进行操作。

React 官方其实是不太推荐使用 refs 去进行 DOM 的操作,因为这会放弃 Virtual DOM 带来的好处——即通过对比虚拟 DOM 树和真实 DOM 树,只重新渲染更新过的 DOM 节点,这样可以省去大量无意义的重复渲染。

React 团队列举出了 3 种使用 refs 的情景:

  • 管理焦点,文本选择或媒体播放。
  • 触发强制动画。
  • 集成第三方 DOM 库。

一般来说,在常规的业务情况下都不太需要用到 refs……至少我到现在没用过。现在创建和使用 refs 的方法也很简单:

class MyComponent extends React.Component {constructor(props) {super(props);// 通过 createRef 创建refthis.myRef = React.createRef();}render() {// 通过 ref={this.{创建的ref实例}} 就能够关联refreturn <div className="exposeRef" ref={this.myRef} />;}
}

这样,类名为 exposeRef 的 div 元素就可以通过操作 this.myRef 的方法去修改。毕竟,refs 也可以通过 props 传递给其他的组件,这样就能够在其他的组件——通常情况下是 MyComponent 的子组件——中直接操作 exposeRef

不受控表单

不受控表单的内容即然无法由 state 控制,那么取值就无法通过 state 去获取了。这种情况下,也只能交给 refs 去处理了,如:

class Form extends Component {constructor() {super();this.name = React.createRef();this.phone = React.createRef();this.onSubmit = this.onSubmit.bind(this);}onSubmit(e) {console.log('submit form');console.log(this.name.current.value, this.phone.current.value);// e.preventDefault(); 放置页面的重定向e.preventDefault();}render() {return (<form onSubmit={this.onSubmit}><div><input type="text" ref={this.name} /></div><div><input type="text" ref={this.phone} /></div><div><input type="submit" value="submit" /></div></form>);}
}

使用效果为:

可以看到第一行的 submit form,以及第二行也成功输出了两个 input 输入框中的值。

如果只需要表单的值,并不需要对表单的内容进行验证,使用不受控表单会方便一些,通过对比同样的代码也能看到,非受控组件的代码量少一些,实现也更简单一些。

相对而言,这种业务的应用范围也相对较少。

注意,还记得 状态 & 状态更新 & 生命周期方法 中提到的报错信息吗:

其中将 input 中的 value 改成 defaultValue 这个解决方案,主要针对的就是非受控组件而进行的提议。在非受控组件中,可以通过添加 defaultValue 这个属性去为其设置默认值。

不受控组件

不受控表单是一种不受控组件,但是不受控组件的应用范围更广一些。

相较于受控组间,不受控组件的使用情况比较少,大多数情况下都会使用到第三方库去对 div 进行管理,如使用一些可视化处理的库,这种情况下也需要搭配 componentWillUnmount 方法去清理由第三方库管理的元素。

例如说 How to properly use componentWillUnmount() in ReactJs 中被采纳的答案就使用了一个案例:

import React from 'react';
import { Component } from 'react';
import ReactDom from 'react-dom';
import d3Chart from './d3charts';export default class Chart extends Component {static propTypes = {data: React.PropTypes.array,domain: React.PropTypes.object,};constructor(props) {super(props);}componentDidMount() {let el = ReactDom.findDOMNode(this);d3Chart.create(el,{width: '100%',height: '300px',},this.getChartState());}componentDidUpdate() {let el = ReactDom.findDOMNode(this);d3Chart.update(el, this.getChartState());}getChartState() {return {data: this.props.data,domain: this.props.domain,};}componentWillUnmount() {let el = ReactDom.findDOMNode(this);d3Chart.destroy(el);}render() {return <div className="Chart"></div>;}
}

这个案例中的 Chart 组件就不包含任何的状态,对图像进行的任何操作,都是由 d3Chart 本身去进行的状态管理。

另外,findDOMNode 这个函数在严格模式下,也就是 <React.StrictMode><其他组件 /></React.StrictMode> 下已经被废弃使用,并且官方建议使用 refs 代替 findDOMNode。

在使用第三方组件的时候一定要记得,如果在 componentDidMount 中有通过绑定 ref/findDOMNode 去创建新对象的情况,那么在 componentWillUnmount 一定要注意去销毁创建的对象,以防内存泄露的情况。

总结

这里主要就表单的内容进行了一定程度的深入了解,并且就非受控表单学习了 refs 的使用,以及在 React 中集成第三方库管理非受控组件需要注意的要点。

总结知识点如下:

  • 受控表单通过 state 去进行状态管理

    受控表单中的知识点包括:

    • ES6 的计算属性

      通过计算属性可以快速更新对象给定参数的值

    • 正确的使用 setState

      这里指代的内容,失去去更新有多个键值对的状态。

      为了性能的提升,React 存在压缩 setState,然后使用 batch update 去更新多个 setState,从而避免频繁的 UI 更新。这个时候,就要采取另外的写法去更新 etState,而不能通过直接调用 this.state 的方法去取值

  • 非受控表单,让页面自己去处理值更新的问题

    通过 refs 去更新和获取值

  • 非受控组件,包含非受控表单,应用范围更广

    采用了 StackOverflow 的一个案例,去学习非受控组件的应用

[React 基础系列] 受控表单 vs 不受控表单相关推荐

  1. 【一起进大厂】7天掌握react基础系列(1)

    导读 本教程适合初学者入门,以及很久没有开发过react项目的同学温故知新.由于本人所在公司,大多数同学原来多数是vue技术栈, 在一次项目组会上分享上面,分享了react的项目,因为大厂基本都用re ...

  2. html表单代码例子_关于React的这些细节,你知道吗?-表单

    在 React 里,HTML 表单元素的工作方式和其他的 DOM 元素有些不同,这是因为表单元素通常会保持一些内部的 state.例如这个纯 HTML 表单只接受一个名称: 此表单具有默认的 HTML ...

  3. STM32 基础系列教程 7 - 单脉冲PWM

    前言 学习stm32 基本定时器的使用,用基本定时器实现产生一个PWM,实现单脉冲PWM的功能. 示例详解 基于硬件平台: STM32F10C8T6最小系统板, MCU 的型号是 STM32F103c ...

  4. 【Educoder】HTML答案 (HTML入门——基础、HTML入门——基本标签、HTML——表单类的标签)

    文章目录 HTML入门--基础 初识HTML:简单的Hello World网页制作 HTML结构:自我简介网页 HTML入门--基本标签 创建第一个 HTML 标签 创建 h2-h6标签 创建 p 标 ...

  5. MySQL基础系列之 记一次利用存储过程实现2600万数据水平分表

    日常开发中我们经常会遇到大表的情况,所谓的大表是指存储了百万级乃至千万级条记录的表.这样的表过于庞大,导致数据库在查询和插入的时候耗时太长,性能低下,如果涉及联合查询的情况,性能会更加糟糕.分表的目的 ...

  6. SQL基础系列(四)——多表查询

    本部分内容包括如何使用2张以上的表如何进行横向联结(表的联结)及竖向联结(集合运算). 目录 1.表的联结 1.1联结是什么 1.2内联结 1.3外联结 1.4多张表联结 1.5复杂表联结语句 2.其 ...

  7. react方法返回html_React全家桶之React基础(推荐新手必看)

    学习目标 安装create-react-app脚手架 熟练React基础语法 掌握JSX语法 掌握setState 掌握React生命周期 掌握props传递参数 掌握React组件通信 资源 rea ...

  8. React基础学习-1

    目录 1.React概述 1.1React简介 1.2 项目搭建 1.3项目结构说明 1.4 React 基本使用 2. JSX 2.1 JSX简介 2.2 JSX中的表达式 2.3 条件渲染 2.4 ...

  9. javascript基础系列(入门前须知)

    -----------------------小历史---------------------------- javascript与java是两种语言,他们的创作公司不同,JavaScript当时是借 ...

最新文章

  1. 工作几年了,API 网关还不懂?
  2. SQLite的数据类型总结
  3. ubuntu 源更新(sources.list)
  4. 图片标签|| 列表标签||链接标签||div和span|| 语义化标签
  5. 附加到IIS进程调试页面
  6. android之http协议编程(源码ppt),Android网络编程(八)源码解析OkHttp中篇[复用连接池]...
  7. elasticSearch 安装和 head插件使用
  8. linux内核编译及添加系统调用(hdu)_浅谈关于Linux内核write系统调用操作的原子性
  9. 世界之窗浏览器怎么隐藏收藏栏
  10. 数据库取图片拼接ImageUrl
  11. 线性回归(一)---一元线性回归
  12. 计算机网络之数据通信基础知识
  13. php文本框清除格式,php如何清除HTML格式
  14. selenium 2定位方式实例
  15. mysql sqrt_详解MySQL中的SQRT函数的使用方法
  16. smale学习之数学表达式(day1)
  17. 替换空格——python
  18. 6264.斐波那契(快速幂)
  19. 软交换总结之二-七号信令
  20. DSG-01-3C4-A110-51T油研液压直动式电磁阀

热门文章

  1. Django——创建数据库和表
  2. thinkphp6+layui BBS社区论坛系统源码分享,支持适配移动端附截图
  3. How does “mov (%ebx,%eax,4),%eax” work?
  4. STM32 CubeMX 1ms定时中断的实现
  5. 视频打开后从头开始_后端软件体系结构清单:如何从头开始构建产品
  6. habor-deploy docker https 私有仓库搭建
  7. 会议oa之排座和送审
  8. 物联网云平台DTU Modbus协议 上位机 下位机 源码 源代码 程序
  9. 算法基础—数据结构—双链表
  10. 部编版是什么版本_人教版是部编还是统编